1 /* Xilinx MicroBlaze-specific support for 32-bit ELF
3 Copyright (C) 2009-2021 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
28 #include "elf/microblaze.h"
31 #define USE_RELA /* Only USE_REL is actually significant, but this is
32 here are a reminder... */
33 #define INST_WORD_SIZE 4
35 static int ro_small_data_pointer
= 0;
36 static int rw_small_data_pointer
= 0;
38 static reloc_howto_type
* microblaze_elf_howto_table
[(int) R_MICROBLAZE_max
];
40 static reloc_howto_type microblaze_elf_howto_raw
[] =
42 /* This reloc does nothing. */
43 HOWTO (R_MICROBLAZE_NONE
, /* Type. */
45 3, /* Size (0 = byte, 1 = short, 2 = long). */
47 false, /* PC_relative. */
49 complain_overflow_dont
, /* Complain on overflow. */
50 NULL
, /* Special Function. */
51 "R_MICROBLAZE_NONE", /* Name. */
52 false, /* Partial Inplace. */
55 false), /* PC relative offset? */
57 /* A standard 32 bit relocation. */
58 HOWTO (R_MICROBLAZE_32
, /* Type. */
60 2, /* Size (0 = byte, 1 = short, 2 = long). */
62 false, /* PC_relative. */
64 complain_overflow_bitfield
, /* Complain on overflow. */
65 bfd_elf_generic_reloc
,/* Special Function. */
66 "R_MICROBLAZE_32", /* Name. */
67 false, /* Partial Inplace. */
69 0xffffffff, /* Dest Mask. */
70 false), /* PC relative offset? */
72 /* A standard PCREL 32 bit relocation. */
73 HOWTO (R_MICROBLAZE_32_PCREL
,/* Type. */
75 2, /* Size (0 = byte, 1 = short, 2 = long). */
77 true, /* PC_relative. */
79 complain_overflow_bitfield
, /* Complain on overflow. */
80 bfd_elf_generic_reloc
,/* Special Function. */
81 "R_MICROBLAZE_32_PCREL", /* Name. */
82 true, /* Partial Inplace. */
84 0xffffffff, /* Dest Mask. */
85 true), /* PC relative offset? */
87 /* A 64 bit PCREL relocation. Table-entry not really used. */
88 HOWTO (R_MICROBLAZE_64_PCREL
,/* Type. */
90 2, /* Size (0 = byte, 1 = short, 2 = long). */
92 true, /* PC_relative. */
94 complain_overflow_dont
, /* Complain on overflow. */
95 bfd_elf_generic_reloc
,/* Special Function. */
96 "R_MICROBLAZE_64_PCREL", /* Name. */
97 false, /* Partial Inplace. */
99 0x0000ffff, /* Dest Mask. */
100 true), /* PC relative offset? */
102 /* The low half of a PCREL 32 bit relocation. */
103 HOWTO (R_MICROBLAZE_32_PCREL_LO
, /* Type. */
105 2, /* Size (0 = byte, 1 = short, 2 = long). */
107 true, /* PC_relative. */
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? */
117 /* A 64 bit relocation. Table entry not really used. */
118 HOWTO (R_MICROBLAZE_64
, /* Type. */
120 2, /* Size (0 = byte, 1 = short, 2 = long). */
122 false, /* PC_relative. */
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? */
132 /* The low half of a 32 bit relocation. */
133 HOWTO (R_MICROBLAZE_32_LO
, /* Type. */
135 2, /* Size (0 = byte, 1 = short, 2 = long). */
137 false, /* PC_relative. */
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? */
147 /* Read-only small data section relocation. */
148 HOWTO (R_MICROBLAZE_SRO32
, /* Type. */
150 2, /* Size (0 = byte, 1 = short, 2 = long). */
152 false, /* PC_relative. */
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? */
162 /* Read-write small data area relocation. */
163 HOWTO (R_MICROBLAZE_SRW32
, /* Type. */
165 2, /* Size (0 = byte, 1 = short, 2 = long). */
167 false, /* PC_relative. */
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? */
177 /* This reloc does nothing. Used for relaxation. */
178 HOWTO (R_MICROBLAZE_64_NONE
, /* Type. */
180 3, /* Size (0 = byte, 1 = short, 2 = long). */
182 true, /* PC_relative. */
184 complain_overflow_dont
, /* Complain on overflow. */
185 NULL
, /* Special Function. */
186 "R_MICROBLAZE_64_NONE",/* Name. */
187 false, /* Partial Inplace. */
188 0, /* Source Mask. */
190 false), /* PC relative offset? */
192 /* Symbol Op Symbol relocation. */
193 HOWTO (R_MICROBLAZE_32_SYM_OP_SYM
, /* Type. */
195 2, /* Size (0 = byte, 1 = short, 2 = long). */
197 false, /* PC_relative. */
199 complain_overflow_bitfield
, /* Complain on overflow. */
200 bfd_elf_generic_reloc
,/* Special Function. */
201 "R_MICROBLAZE_32_SYM_OP_SYM", /* Name. */
202 false, /* Partial Inplace. */
203 0, /* Source Mask. */
204 0xffffffff, /* Dest Mask. */
205 false), /* PC relative offset? */
207 /* GNU extension to record C++ vtable hierarchy. */
208 HOWTO (R_MICROBLAZE_GNU_VTINHERIT
, /* Type. */
210 2, /* Size (0 = byte, 1 = short, 2 = long). */
212 false, /* PC_relative. */
214 complain_overflow_dont
,/* Complain on overflow. */
215 NULL
, /* Special Function. */
216 "R_MICROBLAZE_GNU_VTINHERIT", /* Name. */
217 false, /* Partial Inplace. */
218 0, /* Source Mask. */
220 false), /* PC relative offset? */
222 /* GNU extension to record C++ vtable member usage. */
223 HOWTO (R_MICROBLAZE_GNU_VTENTRY
, /* Type. */
225 2, /* Size (0 = byte, 1 = short, 2 = long). */
227 false, /* PC_relative. */
229 complain_overflow_dont
,/* Complain on overflow. */
230 _bfd_elf_rel_vtable_reloc_fn
, /* Special Function. */
231 "R_MICROBLAZE_GNU_VTENTRY", /* Name. */
232 false, /* Partial Inplace. */
233 0, /* Source Mask. */
235 false), /* PC relative offset? */
237 /* A 64 bit GOTPC relocation. Table-entry not really used. */
238 HOWTO (R_MICROBLAZE_GOTPC_64
, /* Type. */
240 2, /* Size (0 = byte, 1 = short, 2 = long). */
242 true, /* PC_relative. */
244 complain_overflow_dont
, /* Complain on overflow. */
245 bfd_elf_generic_reloc
, /* Special Function. */
246 "R_MICROBLAZE_GOTPC_64", /* Name. */
247 false, /* Partial Inplace. */
248 0, /* Source Mask. */
249 0x0000ffff, /* Dest Mask. */
250 true), /* PC relative offset? */
252 /* A 64 bit TEXTPCREL relocation. Table-entry not really used. */
253 HOWTO (R_MICROBLAZE_TEXTPCREL_64
, /* Type. */
255 2, /* Size (0 = byte, 1 = short, 2 = long). */
257 true, /* PC_relative. */
259 complain_overflow_dont
, /* Complain on overflow. */
260 bfd_elf_generic_reloc
, /* Special Function. */
261 "R_MICROBLAZE_TEXTPCREL_64", /* Name. */
262 false, /* Partial Inplace. */
263 0, /* Source Mask. */
264 0x0000ffff, /* Dest Mask. */
265 true), /* PC relative offset? */
267 /* A 64 bit GOT relocation. Table-entry not really used. */
268 HOWTO (R_MICROBLAZE_GOT_64
, /* Type. */
270 2, /* Size (0 = byte, 1 = short, 2 = long). */
272 false, /* PC_relative. */
274 complain_overflow_dont
, /* Complain on overflow. */
275 bfd_elf_generic_reloc
,/* Special Function. */
276 "R_MICROBLAZE_GOT_64",/* Name. */
277 false, /* Partial Inplace. */
278 0, /* Source Mask. */
279 0x0000ffff, /* Dest Mask. */
280 false), /* PC relative offset? */
282 /* A 64 bit TEXTREL relocation. Table-entry not really used. */
283 HOWTO (R_MICROBLAZE_TEXTREL_64
, /* Type. */
285 2, /* Size (0 = byte, 1 = short, 2 = long). */
287 false, /* PC_relative. */
289 complain_overflow_dont
, /* Complain on overflow. */
290 bfd_elf_generic_reloc
,/* Special Function. */
291 "R_MICROBLAZE_TEXTREL_64",/* Name. */
292 false, /* Partial Inplace. */
293 0, /* Source Mask. */
294 0x0000ffff, /* Dest Mask. */
295 false), /* PC relative offset? */
297 /* A 64 bit PLT relocation. Table-entry not really used. */
298 HOWTO (R_MICROBLAZE_PLT_64
, /* Type. */
300 2, /* Size (0 = byte, 1 = short, 2 = long). */
302 true, /* PC_relative. */
304 complain_overflow_dont
, /* Complain on overflow. */
305 bfd_elf_generic_reloc
,/* Special Function. */
306 "R_MICROBLAZE_PLT_64",/* Name. */
307 false, /* Partial Inplace. */
308 0, /* Source Mask. */
309 0x0000ffff, /* Dest Mask. */
310 true), /* PC relative offset? */
312 /* Table-entry not really used. */
313 HOWTO (R_MICROBLAZE_REL
, /* Type. */
315 2, /* Size (0 = byte, 1 = short, 2 = long). */
317 true, /* PC_relative. */
319 complain_overflow_dont
, /* Complain on overflow. */
320 bfd_elf_generic_reloc
,/* Special Function. */
321 "R_MICROBLAZE_REL", /* Name. */
322 false, /* Partial Inplace. */
323 0, /* Source Mask. */
324 0x0000ffff, /* Dest Mask. */
325 true), /* PC relative offset? */
327 /* Table-entry not really used. */
328 HOWTO (R_MICROBLAZE_JUMP_SLOT
,/* Type. */
330 2, /* Size (0 = byte, 1 = short, 2 = long). */
332 true, /* PC_relative. */
334 complain_overflow_dont
, /* Complain on overflow. */
335 bfd_elf_generic_reloc
,/* Special Function. */
336 "R_MICROBLAZE_JUMP_SLOT", /* Name. */
337 false, /* Partial Inplace. */
338 0, /* Source Mask. */
339 0x0000ffff, /* Dest Mask. */
340 true), /* PC relative offset? */
342 /* Table-entry not really used. */
343 HOWTO (R_MICROBLAZE_GLOB_DAT
,/* Type. */
345 2, /* Size (0 = byte, 1 = short, 2 = long). */
347 true, /* PC_relative. */
349 complain_overflow_dont
, /* Complain on overflow. */
350 bfd_elf_generic_reloc
,/* Special Function. */
351 "R_MICROBLAZE_GLOB_DAT", /* Name. */
352 false, /* Partial Inplace. */
353 0, /* Source Mask. */
354 0x0000ffff, /* Dest Mask. */
355 true), /* PC relative offset? */
357 /* A 64 bit GOT relative relocation. Table-entry not really used. */
358 HOWTO (R_MICROBLAZE_GOTOFF_64
, /* Type. */
360 2, /* Size (0 = byte, 1 = short, 2 = long). */
362 false, /* PC_relative. */
364 complain_overflow_dont
, /* Complain on overflow. */
365 bfd_elf_generic_reloc
,/* Special Function. */
366 "R_MICROBLAZE_GOTOFF_64", /* Name. */
367 false, /* Partial Inplace. */
368 0, /* Source Mask. */
369 0x0000ffff, /* Dest Mask. */
370 false), /* PC relative offset? */
372 /* A 32 bit GOT relative relocation. Table-entry not really used. */
373 HOWTO (R_MICROBLAZE_GOTOFF_32
, /* Type. */
375 2, /* Size (0 = byte, 1 = short, 2 = long). */
377 false, /* PC_relative. */
379 complain_overflow_dont
, /* Complain on overflow. */
380 bfd_elf_generic_reloc
, /* Special Function. */
381 "R_MICROBLAZE_GOTOFF_32", /* Name. */
382 false, /* Partial Inplace. */
383 0, /* Source Mask. */
384 0x0000ffff, /* Dest Mask. */
385 false), /* PC relative offset? */
387 /* COPY relocation. Table-entry not really used. */
388 HOWTO (R_MICROBLAZE_COPY
, /* Type. */
390 2, /* Size (0 = byte, 1 = short, 2 = long). */
392 false, /* PC_relative. */
394 complain_overflow_dont
, /* Complain on overflow. */
395 bfd_elf_generic_reloc
,/* Special Function. */
396 "R_MICROBLAZE_COPY", /* Name. */
397 false, /* Partial Inplace. */
398 0, /* Source Mask. */
399 0x0000ffff, /* Dest Mask. */
400 false), /* PC relative offset? */
402 /* Marker relocs for TLS. */
403 HOWTO (R_MICROBLAZE_TLS
,
405 2, /* size (0 = byte, 1 = short, 2 = long) */
407 false, /* pc_relative */
409 complain_overflow_dont
, /* complain_on_overflow */
410 bfd_elf_generic_reloc
, /* special_function */
411 "R_MICROBLAZE_TLS", /* name */
412 false, /* partial_inplace */
414 0x0000ffff, /* dst_mask */
415 false), /* pcrel_offset */
417 HOWTO (R_MICROBLAZE_TLSGD
,
419 2, /* size (0 = byte, 1 = short, 2 = long) */
421 false, /* pc_relative */
423 complain_overflow_dont
, /* complain_on_overflow */
424 bfd_elf_generic_reloc
, /* special_function */
425 "R_MICROBLAZE_TLSGD", /* name */
426 false, /* partial_inplace */
428 0x0000ffff, /* dst_mask */
429 false), /* pcrel_offset */
431 HOWTO (R_MICROBLAZE_TLSLD
,
433 2, /* size (0 = byte, 1 = short, 2 = long) */
435 false, /* pc_relative */
437 complain_overflow_dont
, /* complain_on_overflow */
438 bfd_elf_generic_reloc
, /* special_function */
439 "R_MICROBLAZE_TLSLD", /* name */
440 false, /* partial_inplace */
442 0x0000ffff, /* dst_mask */
443 false), /* pcrel_offset */
445 /* Computes the load module index of the load module that contains the
446 definition of its TLS sym. */
447 HOWTO (R_MICROBLAZE_TLSDTPMOD32
,
449 2, /* size (0 = byte, 1 = short, 2 = long) */
451 false, /* pc_relative */
453 complain_overflow_dont
, /* complain_on_overflow */
454 bfd_elf_generic_reloc
, /* special_function */
455 "R_MICROBLAZE_TLSDTPMOD32", /* name */
456 false, /* partial_inplace */
458 0x0000ffff, /* dst_mask */
459 false), /* pcrel_offset */
461 /* Computes a dtv-relative displacement, the difference between the value
462 of sym+add and the base address of the thread-local storage block that
463 contains the definition of sym, minus 0x8000. Used for initializing GOT */
464 HOWTO (R_MICROBLAZE_TLSDTPREL32
,
466 2, /* size (0 = byte, 1 = short, 2 = long) */
468 false, /* pc_relative */
470 complain_overflow_dont
, /* complain_on_overflow */
471 bfd_elf_generic_reloc
, /* special_function */
472 "R_MICROBLAZE_TLSDTPREL32", /* name */
473 false, /* partial_inplace */
475 0x0000ffff, /* dst_mask */
476 false), /* pcrel_offset */
478 /* Computes a dtv-relative displacement, the difference between the value
479 of sym+add and the base address of the thread-local storage block that
480 contains the definition of sym, minus 0x8000. */
481 HOWTO (R_MICROBLAZE_TLSDTPREL64
,
483 2, /* size (0 = byte, 1 = short, 2 = long) */
485 false, /* pc_relative */
487 complain_overflow_dont
, /* complain_on_overflow */
488 bfd_elf_generic_reloc
, /* special_function */
489 "R_MICROBLAZE_TLSDTPREL64", /* name */
490 false, /* partial_inplace */
492 0x0000ffff, /* dst_mask */
493 false), /* pcrel_offset */
495 /* Computes a tp-relative displacement, the difference between the value of
496 sym+add and the value of the thread pointer (r13). */
497 HOWTO (R_MICROBLAZE_TLSGOTTPREL32
,
499 2, /* size (0 = byte, 1 = short, 2 = long) */
501 false, /* pc_relative */
503 complain_overflow_dont
, /* complain_on_overflow */
504 bfd_elf_generic_reloc
, /* special_function */
505 "R_MICROBLAZE_TLSGOTTPREL32", /* name */
506 false, /* partial_inplace */
508 0x0000ffff, /* dst_mask */
509 false), /* pcrel_offset */
511 /* Computes a tp-relative displacement, the difference between the value of
512 sym+add and the value of the thread pointer (r13). */
513 HOWTO (R_MICROBLAZE_TLSTPREL32
,
515 2, /* size (0 = byte, 1 = short, 2 = long) */
517 false, /* pc_relative */
519 complain_overflow_dont
, /* complain_on_overflow */
520 bfd_elf_generic_reloc
, /* special_function */
521 "R_MICROBLAZE_TLSTPREL32", /* name */
522 false, /* partial_inplace */
524 0x0000ffff, /* dst_mask */
525 false), /* pcrel_offset */
530 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
533 /* Initialize the microblaze_elf_howto_table, so that linear accesses can be done. */
536 microblaze_elf_howto_init (void)
540 for (i
= NUM_ELEM (microblaze_elf_howto_raw
); i
--;)
544 type
= microblaze_elf_howto_raw
[i
].type
;
546 BFD_ASSERT (type
< NUM_ELEM (microblaze_elf_howto_table
));
548 microblaze_elf_howto_table
[type
] = & microblaze_elf_howto_raw
[i
];
552 static reloc_howto_type
*
553 microblaze_elf_reloc_type_lookup (bfd
* abfd ATTRIBUTE_UNUSED
,
554 bfd_reloc_code_real_type code
)
556 enum elf_microblaze_reloc_type microblaze_reloc
= R_MICROBLAZE_NONE
;
561 microblaze_reloc
= R_MICROBLAZE_NONE
;
563 case BFD_RELOC_MICROBLAZE_64_NONE
:
564 microblaze_reloc
= R_MICROBLAZE_64_NONE
;
567 microblaze_reloc
= R_MICROBLAZE_32
;
569 /* RVA is treated the same as 32 */
571 microblaze_reloc
= R_MICROBLAZE_32
;
573 case BFD_RELOC_32_PCREL
:
574 microblaze_reloc
= R_MICROBLAZE_32_PCREL
;
576 case BFD_RELOC_64_PCREL
:
577 microblaze_reloc
= R_MICROBLAZE_64_PCREL
;
579 case BFD_RELOC_MICROBLAZE_32_LO_PCREL
:
580 microblaze_reloc
= R_MICROBLAZE_32_PCREL_LO
;
583 microblaze_reloc
= R_MICROBLAZE_64
;
585 case BFD_RELOC_MICROBLAZE_32_LO
:
586 microblaze_reloc
= R_MICROBLAZE_32_LO
;
588 case BFD_RELOC_MICROBLAZE_32_ROSDA
:
589 microblaze_reloc
= R_MICROBLAZE_SRO32
;
591 case BFD_RELOC_MICROBLAZE_32_RWSDA
:
592 microblaze_reloc
= R_MICROBLAZE_SRW32
;
594 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM
:
595 microblaze_reloc
= R_MICROBLAZE_32_SYM_OP_SYM
;
597 case BFD_RELOC_VTABLE_INHERIT
:
598 microblaze_reloc
= R_MICROBLAZE_GNU_VTINHERIT
;
600 case BFD_RELOC_VTABLE_ENTRY
:
601 microblaze_reloc
= R_MICROBLAZE_GNU_VTENTRY
;
603 case BFD_RELOC_MICROBLAZE_64_GOTPC
:
604 microblaze_reloc
= R_MICROBLAZE_GOTPC_64
;
606 case BFD_RELOC_MICROBLAZE_64_GOT
:
607 microblaze_reloc
= R_MICROBLAZE_GOT_64
;
609 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL
:
610 microblaze_reloc
= R_MICROBLAZE_TEXTPCREL_64
;
612 case BFD_RELOC_MICROBLAZE_64_TEXTREL
:
613 microblaze_reloc
= R_MICROBLAZE_TEXTREL_64
;
615 case BFD_RELOC_MICROBLAZE_64_PLT
:
616 microblaze_reloc
= R_MICROBLAZE_PLT_64
;
618 case BFD_RELOC_MICROBLAZE_64_GOTOFF
:
619 microblaze_reloc
= R_MICROBLAZE_GOTOFF_64
;
621 case BFD_RELOC_MICROBLAZE_32_GOTOFF
:
622 microblaze_reloc
= R_MICROBLAZE_GOTOFF_32
;
624 case BFD_RELOC_MICROBLAZE_64_TLSGD
:
625 microblaze_reloc
= R_MICROBLAZE_TLSGD
;
627 case BFD_RELOC_MICROBLAZE_64_TLSLD
:
628 microblaze_reloc
= R_MICROBLAZE_TLSLD
;
630 case BFD_RELOC_MICROBLAZE_32_TLSDTPREL
:
631 microblaze_reloc
= R_MICROBLAZE_TLSDTPREL32
;
633 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL
:
634 microblaze_reloc
= R_MICROBLAZE_TLSDTPREL64
;
636 case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD
:
637 microblaze_reloc
= R_MICROBLAZE_TLSDTPMOD32
;
639 case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL
:
640 microblaze_reloc
= R_MICROBLAZE_TLSGOTTPREL32
;
642 case BFD_RELOC_MICROBLAZE_64_TLSTPREL
:
643 microblaze_reloc
= R_MICROBLAZE_TLSTPREL32
;
645 case BFD_RELOC_MICROBLAZE_COPY
:
646 microblaze_reloc
= R_MICROBLAZE_COPY
;
649 return (reloc_howto_type
*) NULL
;
652 if (!microblaze_elf_howto_table
[R_MICROBLAZE_32
])
653 /* Initialize howto table if needed. */
654 microblaze_elf_howto_init ();
656 return microblaze_elf_howto_table
[(int) microblaze_reloc
];
659 static reloc_howto_type
*
660 microblaze_elf_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
665 for (i
= 0; i
< NUM_ELEM (microblaze_elf_howto_raw
); i
++)
666 if (microblaze_elf_howto_raw
[i
].name
!= NULL
667 && strcasecmp (microblaze_elf_howto_raw
[i
].name
, r_name
) == 0)
668 return µblaze_elf_howto_raw
[i
];
673 /* Set the howto pointer for a RCE ELF reloc. */
676 microblaze_elf_info_to_howto (bfd
* abfd
,
678 Elf_Internal_Rela
* dst
)
682 if (!microblaze_elf_howto_table
[R_MICROBLAZE_32
])
683 /* Initialize howto table if needed. */
684 microblaze_elf_howto_init ();
686 r_type
= ELF32_R_TYPE (dst
->r_info
);
687 if (r_type
>= R_MICROBLAZE_max
)
689 /* xgettext:c-format */
690 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
692 bfd_set_error (bfd_error_bad_value
);
696 cache_ptr
->howto
= microblaze_elf_howto_table
[r_type
];
700 /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'. */
703 microblaze_elf_is_local_label_name (bfd
*abfd
, const char *name
)
705 if (name
[0] == 'L' && name
[1] == '.')
708 if (name
[0] == '$' && name
[1] == 'L')
711 /* With gcc, the labels go back to starting with '.', so we accept
712 the generic ELF local label syntax as well. */
713 return _bfd_elf_is_local_label_name (abfd
, name
);
716 /* ELF linker hash entry. */
718 struct elf32_mb_link_hash_entry
720 struct elf_link_hash_entry elf
;
722 /* TLS Reference Types for the symbol; Updated by check_relocs */
723 #define TLS_GD 1 /* GD reloc. */
724 #define TLS_LD 2 /* LD reloc. */
725 #define TLS_TPREL 4 /* TPREL reloc, => IE. */
726 #define TLS_DTPREL 8 /* DTPREL reloc, => LD. */
727 #define TLS_TLS 16 /* Any TLS reloc. */
728 unsigned char tls_mask
;
732 #define IS_TLS_GD(x) (x == (TLS_TLS | TLS_GD))
733 #define IS_TLS_LD(x) (x == (TLS_TLS | TLS_LD))
734 #define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
735 #define IS_TLS_NONE(x) (x == 0)
737 #define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
739 /* ELF linker hash table. */
741 struct elf32_mb_link_hash_table
743 struct elf_link_hash_table elf
;
745 /* TLS Local Dynamic GOT Entry */
747 bfd_signed_vma refcount
;
752 /* Nonzero if this section has TLS related relocations. */
753 #define has_tls_reloc sec_flg0
755 /* Get the ELF linker hash table from a link_info structure. */
757 #define elf32_mb_hash_table(p) \
758 ((is_elf_hash_table ((p)->hash) \
759 && elf_hash_table_id (elf_hash_table (p)) == MICROBLAZE_ELF_DATA) \
760 ? (struct elf32_mb_link_hash_table *) (p)->hash : NULL)
762 /* Create an entry in a microblaze ELF linker hash table. */
764 static struct bfd_hash_entry
*
765 link_hash_newfunc (struct bfd_hash_entry
*entry
,
766 struct bfd_hash_table
*table
,
769 /* Allocate the structure if it has not already been allocated by a
773 entry
= bfd_hash_allocate (table
,
774 sizeof (struct elf32_mb_link_hash_entry
));
779 /* Call the allocation method of the superclass. */
780 entry
= _bfd_elf_link_hash_newfunc (entry
, table
, string
);
783 struct elf32_mb_link_hash_entry
*eh
;
785 eh
= (struct elf32_mb_link_hash_entry
*) entry
;
792 /* Create a mb ELF linker hash table. */
794 static struct bfd_link_hash_table
*
795 microblaze_elf_link_hash_table_create (bfd
*abfd
)
797 struct elf32_mb_link_hash_table
*ret
;
798 size_t amt
= sizeof (struct elf32_mb_link_hash_table
);
800 ret
= (struct elf32_mb_link_hash_table
*) bfd_zmalloc (amt
);
804 if (!_bfd_elf_link_hash_table_init (&ret
->elf
, abfd
, link_hash_newfunc
,
805 sizeof (struct elf32_mb_link_hash_entry
),
806 MICROBLAZE_ELF_DATA
))
812 return &ret
->elf
.root
;
815 /* Set the values of the small data pointers. */
818 microblaze_elf_final_sdp (struct bfd_link_info
*info
)
820 struct bfd_link_hash_entry
*h
;
822 h
= bfd_link_hash_lookup (info
->hash
, RO_SDA_ANCHOR_NAME
, false, false, true);
823 if (h
!= (struct bfd_link_hash_entry
*) NULL
824 && h
->type
== bfd_link_hash_defined
)
825 ro_small_data_pointer
= (h
->u
.def
.value
826 + h
->u
.def
.section
->output_section
->vma
827 + h
->u
.def
.section
->output_offset
);
829 h
= bfd_link_hash_lookup (info
->hash
, RW_SDA_ANCHOR_NAME
, false, false, true);
830 if (h
!= (struct bfd_link_hash_entry
*) NULL
831 && h
->type
== bfd_link_hash_defined
)
832 rw_small_data_pointer
= (h
->u
.def
.value
833 + h
->u
.def
.section
->output_section
->vma
834 + h
->u
.def
.section
->output_offset
);
838 dtprel_base (struct bfd_link_info
*info
)
840 /* If tls_sec is NULL, we should have signalled an error already. */
841 if (elf_hash_table (info
)->tls_sec
== NULL
)
843 return elf_hash_table (info
)->tls_sec
->vma
;
846 /* The size of the thread control block. */
849 /* Output a simple dynamic relocation into SRELOC. */
852 microblaze_elf_output_dynamic_relocation (bfd
*output_bfd
,
854 unsigned long reloc_index
,
861 Elf_Internal_Rela rel
;
863 rel
.r_info
= ELF32_R_INFO (indx
, r_type
);
864 rel
.r_offset
= offset
;
865 rel
.r_addend
= addend
;
867 bfd_elf32_swap_reloca_out (output_bfd
, &rel
,
868 (sreloc
->contents
+ reloc_index
* sizeof (Elf32_External_Rela
)));
871 /* This code is taken from elf32-m32r.c
872 There is some attempt to make this function usable for many architectures,
873 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
874 if only to serve as a learning tool.
876 The RELOCATE_SECTION function is called by the new ELF backend linker
877 to handle the relocations for a section.
879 The relocs are always passed as Rela structures; if the section
880 actually uses Rel structures, the r_addend field will always be
883 This function is responsible for adjust the section contents as
884 necessary, and (if using Rela relocs and generating a
885 relocatable output file) adjusting the reloc addend as
888 This function does not have to worry about setting the reloc
889 address or the reloc symbol index.
891 LOCAL_SYMS is a pointer to the swapped in local symbols.
893 LOCAL_SECTIONS is an array giving the section in the input file
894 corresponding to the st_shndx field of each local symbol.
896 The global hash table entry for the global symbols can be found
897 via elf_sym_hashes (input_bfd).
899 When generating relocatable output, this function must handle
900 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
901 going to be the section symbol corresponding to the output
902 section, which means that the addend must be adjusted
906 microblaze_elf_relocate_section (bfd
*output_bfd
,
907 struct bfd_link_info
*info
,
909 asection
*input_section
,
911 Elf_Internal_Rela
*relocs
,
912 Elf_Internal_Sym
*local_syms
,
913 asection
**local_sections
)
915 struct elf32_mb_link_hash_table
*htab
;
916 Elf_Internal_Shdr
*symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
917 struct elf_link_hash_entry
**sym_hashes
= elf_sym_hashes (input_bfd
);
918 Elf_Internal_Rela
*rel
, *relend
;
919 int endian
= (bfd_little_endian (output_bfd
)) ? 0 : 2;
920 /* Assume success. */
923 bfd_vma
*local_got_offsets
;
924 unsigned int tls_type
;
926 if (!microblaze_elf_howto_table
[R_MICROBLAZE_max
-1])
927 microblaze_elf_howto_init ();
929 htab
= elf32_mb_hash_table (info
);
933 local_got_offsets
= elf_local_got_offsets (input_bfd
);
935 sreloc
= elf_section_data (input_section
)->sreloc
;
938 relend
= relocs
+ input_section
->reloc_count
;
939 for (; rel
< relend
; rel
++)
942 reloc_howto_type
*howto
;
943 unsigned long r_symndx
;
944 bfd_vma addend
= rel
->r_addend
;
945 bfd_vma offset
= rel
->r_offset
;
946 struct elf_link_hash_entry
*h
;
947 Elf_Internal_Sym
*sym
;
949 const char *sym_name
;
950 bfd_reloc_status_type r
= bfd_reloc_ok
;
951 const char *errmsg
= NULL
;
952 bool unresolved_reloc
= false;
955 r_type
= ELF32_R_TYPE (rel
->r_info
);
958 if (r_type
< 0 || r_type
>= (int) R_MICROBLAZE_max
)
960 /* xgettext:c-format */
961 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
962 input_bfd
, (int) r_type
);
963 bfd_set_error (bfd_error_bad_value
);
968 howto
= microblaze_elf_howto_table
[r_type
];
969 r_symndx
= ELF32_R_SYM (rel
->r_info
);
971 if (bfd_link_relocatable (info
))
973 /* This is a relocatable link. We don't have to change
974 anything, unless the reloc is against a section symbol,
975 in which case we have to adjust according to where the
976 section symbol winds up in the output section. */
978 if (r_symndx
>= symtab_hdr
->sh_info
)
979 /* External symbol. */
983 sym
= local_syms
+ r_symndx
;
984 sym_name
= "<local symbol>";
985 /* STT_SECTION: symbol is associated with a section. */
986 if (ELF_ST_TYPE (sym
->st_info
) != STT_SECTION
)
987 /* Symbol isn't associated with a section. Nothing to do. */
990 sec
= local_sections
[r_symndx
];
991 addend
+= sec
->output_offset
+ sym
->st_value
;
993 /* This can't be done for USE_REL because it doesn't mean anything
994 and elf_link_input_bfd asserts this stays zero. */
995 /* rel->r_addend = addend; */
999 /* Addends are stored with relocs. We're done. */
1002 /* If partial_inplace, we need to store any additional addend
1003 back in the section. */
1004 if (!howto
->partial_inplace
)
1006 /* ??? Here is a nice place to call a special_function like handler. */
1007 r
= _bfd_relocate_contents (howto
, input_bfd
, addend
,
1009 #endif /* USE_REL */
1014 bool resolved_to_zero
;
1016 /* This is a final link. */
1019 unresolved_reloc
= false;
1021 if (r_symndx
< symtab_hdr
->sh_info
)
1024 sym
= local_syms
+ r_symndx
;
1025 sec
= local_sections
[r_symndx
];
1028 sym_name
= "<local symbol>";
1029 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
1030 /* r_addend may have changed if the reference section was
1032 addend
= rel
->r_addend
;
1036 /* External symbol. */
1037 bool warned ATTRIBUTE_UNUSED
;
1038 bool ignored ATTRIBUTE_UNUSED
;
1040 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
1041 r_symndx
, symtab_hdr
, sym_hashes
,
1043 unresolved_reloc
, warned
, ignored
);
1044 sym_name
= h
->root
.root
.string
;
1047 /* Sanity check the address. */
1048 if (offset
> bfd_get_section_limit (input_bfd
, input_section
))
1050 r
= bfd_reloc_outofrange
;
1054 resolved_to_zero
= (h
!= NULL
1055 && UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
));
1057 switch ((int) r_type
)
1059 case (int) R_MICROBLAZE_SRO32
:
1063 /* Only relocate if the symbol is defined. */
1066 name
= bfd_section_name (sec
);
1068 if (strcmp (name
, ".sdata2") == 0
1069 || strcmp (name
, ".sbss2") == 0)
1071 if (ro_small_data_pointer
== 0)
1072 microblaze_elf_final_sdp (info
);
1073 if (ro_small_data_pointer
== 0)
1076 r
= bfd_reloc_undefined
;
1080 /* At this point `relocation' contains the object's
1082 relocation
-= ro_small_data_pointer
;
1083 /* Now it contains the offset from _SDA2_BASE_. */
1084 r
= _bfd_final_link_relocate (howto
, input_bfd
,
1087 relocation
, addend
);
1092 /* xgettext:c-format */
1093 (_("%pB: the target (%s) of an %s relocation"
1094 " is in the wrong section (%pA)"),
1097 microblaze_elf_howto_table
[(int) r_type
]->name
,
1099 /*bfd_set_error (bfd_error_bad_value); ??? why? */
1107 case (int) R_MICROBLAZE_SRW32
:
1111 /* Only relocate if the symbol is defined. */
1114 name
= bfd_section_name (sec
);
1116 if (strcmp (name
, ".sdata") == 0
1117 || strcmp (name
, ".sbss") == 0)
1119 if (rw_small_data_pointer
== 0)
1120 microblaze_elf_final_sdp (info
);
1121 if (rw_small_data_pointer
== 0)
1124 r
= bfd_reloc_undefined
;
1128 /* At this point `relocation' contains the object's
1130 relocation
-= rw_small_data_pointer
;
1131 /* Now it contains the offset from _SDA_BASE_. */
1132 r
= _bfd_final_link_relocate (howto
, input_bfd
,
1135 relocation
, addend
);
1140 /* xgettext:c-format */
1141 (_("%pB: the target (%s) of an %s relocation"
1142 " is in the wrong section (%pA)"),
1145 microblaze_elf_howto_table
[(int) r_type
]->name
,
1147 /*bfd_set_error (bfd_error_bad_value); ??? why? */
1155 case (int) R_MICROBLAZE_32_SYM_OP_SYM
:
1156 break; /* Do nothing. */
1158 case (int) R_MICROBLAZE_GOTPC_64
:
1159 relocation
= (htab
->elf
.sgotplt
->output_section
->vma
1160 + htab
->elf
.sgotplt
->output_offset
);
1161 relocation
-= (input_section
->output_section
->vma
1162 + input_section
->output_offset
1163 + offset
+ INST_WORD_SIZE
);
1164 relocation
+= addend
;
1165 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1166 contents
+ offset
+ endian
);
1167 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1168 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1171 case (int) R_MICROBLAZE_TEXTPCREL_64
:
1172 relocation
= input_section
->output_section
->vma
;
1173 relocation
-= (input_section
->output_section
->vma
1174 + input_section
->output_offset
1175 + offset
+ INST_WORD_SIZE
);
1176 relocation
+= addend
;
1177 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1178 contents
+ offset
+ endian
);
1179 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1180 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1183 case (int) R_MICROBLAZE_PLT_64
:
1186 if (htab
->elf
.splt
!= NULL
&& h
!= NULL
1187 && h
->plt
.offset
!= (bfd_vma
) -1)
1189 relocation
= (htab
->elf
.splt
->output_section
->vma
1190 + htab
->elf
.splt
->output_offset
1192 unresolved_reloc
= false;
1193 immediate
= relocation
- (input_section
->output_section
->vma
1194 + input_section
->output_offset
1195 + offset
+ INST_WORD_SIZE
);
1196 bfd_put_16 (input_bfd
, (immediate
>> 16) & 0xffff,
1197 contents
+ offset
+ endian
);
1198 bfd_put_16 (input_bfd
, immediate
& 0xffff,
1199 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1203 relocation
-= (input_section
->output_section
->vma
1204 + input_section
->output_offset
1205 + offset
+ INST_WORD_SIZE
);
1206 immediate
= relocation
;
1207 bfd_put_16 (input_bfd
, (immediate
>> 16) & 0xffff,
1208 contents
+ offset
+ endian
);
1209 bfd_put_16 (input_bfd
, immediate
& 0xffff,
1210 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1215 case (int) R_MICROBLAZE_TLSGD
:
1216 tls_type
= (TLS_TLS
| TLS_GD
);
1218 case (int) R_MICROBLAZE_TLSLD
:
1219 tls_type
= (TLS_TLS
| TLS_LD
);
1222 case (int) R_MICROBLAZE_GOT_64
:
1227 bfd_vma static_value
;
1229 bool need_relocs
= false;
1230 if (htab
->elf
.sgot
== NULL
)
1236 /* 1. Identify GOT Offset;
1237 2. Compute Static Values
1238 3. Process Module Id, Process Offset
1239 4. Fixup Relocation with GOT offset value. */
1241 /* 1. Determine GOT Offset to use : TLS_LD, global, local */
1242 if (IS_TLS_LD (tls_type
))
1243 offp
= &htab
->tlsld_got
.offset
;
1246 if (htab
->elf
.sgotplt
!= NULL
1247 && h
->got
.offset
!= (bfd_vma
) -1)
1248 offp
= &h
->got
.offset
;
1254 if (local_got_offsets
== NULL
)
1256 offp
= &local_got_offsets
[r_symndx
];
1265 if (IS_TLS_LD(tls_type
) || IS_TLS_GD(tls_type
))
1268 /* Symbol index to use for relocs */
1272 elf_hash_table (info
)->dynamic_sections_created
;
1274 if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn
,
1275 bfd_link_pic (info
),
1277 && (!bfd_link_pic (info
)
1278 || !SYMBOL_REFERENCES_LOCAL (info
, h
)))
1282 /* Need to generate relocs ? */
1283 if ((bfd_link_pic (info
) || indx
!= 0)
1285 || (ELF_ST_VISIBILITY (h
->other
) == STV_DEFAULT
1286 && !resolved_to_zero
)
1287 || h
->root
.type
!= bfd_link_hash_undefweak
))
1290 /* 2. Compute/Emit Static value of r-expression */
1291 static_value
= relocation
+ addend
;
1293 /* 3. Process module-id and offset */
1294 if (! ((*offp
) & 1) )
1298 got_offset
= (htab
->elf
.sgot
->output_section
->vma
1299 + htab
->elf
.sgot
->output_offset
1302 /* Process module-id */
1303 if (IS_TLS_LD(tls_type
))
1305 if (! bfd_link_pic (info
))
1306 bfd_put_32 (output_bfd
, 1,
1307 htab
->elf
.sgot
->contents
+ off
);
1309 microblaze_elf_output_dynamic_relocation
1312 htab
->elf
.srelgot
->reloc_count
++,
1313 /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32
,
1316 else if (IS_TLS_GD(tls_type
))
1319 bfd_put_32 (output_bfd
, 1,
1320 htab
->elf
.sgot
->contents
+ off
);
1322 microblaze_elf_output_dynamic_relocation
1325 htab
->elf
.srelgot
->reloc_count
++,
1326 /* symindex= */ indx
, R_MICROBLAZE_TLSDTPMOD32
,
1327 got_offset
, indx
? 0 : static_value
);
1330 /* Process Offset */
1331 if (htab
->elf
.srelgot
== NULL
)
1334 got_offset
= (htab
->elf
.sgot
->output_section
->vma
1335 + htab
->elf
.sgot
->output_offset
1337 if (IS_TLS_LD(tls_type
))
1339 /* For LD, offset should be 0 */
1341 bfd_put_32 (output_bfd
, 0,
1342 htab
->elf
.sgot
->contents
+ off2
);
1344 else if (IS_TLS_GD(tls_type
))
1347 static_value
-= dtprel_base(info
);
1349 microblaze_elf_output_dynamic_relocation
1352 htab
->elf
.srelgot
->reloc_count
++,
1353 /* symindex= */ indx
, R_MICROBLAZE_TLSDTPREL32
,
1354 got_offset
, indx
? 0 : static_value
);
1356 bfd_put_32 (output_bfd
, static_value
,
1357 htab
->elf
.sgot
->contents
+ off2
);
1361 bfd_put_32 (output_bfd
, static_value
,
1362 htab
->elf
.sgot
->contents
+ off2
);
1364 /* Relocs for dyn symbols generated by
1365 finish_dynamic_symbols */
1366 if (bfd_link_pic (info
) && h
== NULL
)
1369 microblaze_elf_output_dynamic_relocation
1372 htab
->elf
.srelgot
->reloc_count
++,
1373 /* symindex= */ indx
, R_MICROBLAZE_REL
,
1374 got_offset
, static_value
);
1379 /* 4. Fixup Relocation with GOT offset value
1380 Compute relative address of GOT entry for applying
1381 the current relocation */
1382 relocation
= htab
->elf
.sgot
->output_section
->vma
1383 + htab
->elf
.sgot
->output_offset
1385 - htab
->elf
.sgotplt
->output_section
->vma
1386 - htab
->elf
.sgotplt
->output_offset
;
1388 /* Apply Current Relocation */
1389 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1390 contents
+ offset
+ endian
);
1391 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1392 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1394 unresolved_reloc
= false;
1398 case (int) R_MICROBLAZE_GOTOFF_64
:
1401 unsigned short lo
, high
;
1402 relocation
+= addend
;
1403 relocation
-= (htab
->elf
.sgotplt
->output_section
->vma
1404 + htab
->elf
.sgotplt
->output_offset
);
1405 /* Write this value into correct location. */
1406 immediate
= relocation
;
1407 lo
= immediate
& 0x0000ffff;
1408 high
= (immediate
>> 16) & 0x0000ffff;
1409 bfd_put_16 (input_bfd
, high
, contents
+ offset
+ endian
);
1410 bfd_put_16 (input_bfd
, lo
,
1411 contents
+ offset
+ INST_WORD_SIZE
+ endian
);
1415 case (int) R_MICROBLAZE_GOTOFF_32
:
1417 relocation
+= addend
;
1418 relocation
-= (htab
->elf
.sgotplt
->output_section
->vma
1419 + htab
->elf
.sgotplt
->output_offset
);
1420 /* Write this value into correct location. */
1421 bfd_put_32 (input_bfd
, relocation
, contents
+ offset
);
1425 case (int) R_MICROBLAZE_TLSDTPREL64
:
1426 relocation
+= addend
;
1427 relocation
-= dtprel_base(info
);
1428 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1429 contents
+ offset
+ 2);
1430 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1431 contents
+ offset
+ 2 + INST_WORD_SIZE
);
1433 case (int) R_MICROBLAZE_TEXTREL_64
:
1434 case (int) R_MICROBLAZE_TEXTREL_32_LO
:
1435 case (int) R_MICROBLAZE_64_PCREL
:
1436 case (int) R_MICROBLAZE_64
:
1437 case (int) R_MICROBLAZE_32
:
1439 /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
1440 from removed linkonce sections, or sections discarded by
1442 if (r_symndx
== STN_UNDEF
|| (input_section
->flags
& SEC_ALLOC
) == 0)
1444 relocation
+= addend
;
1445 if (r_type
== R_MICROBLAZE_32
)
1446 bfd_put_32 (input_bfd
, relocation
, contents
+ offset
);
1449 if (r_type
== R_MICROBLAZE_64_PCREL
)
1450 relocation
-= (input_section
->output_section
->vma
1451 + input_section
->output_offset
1452 + offset
+ INST_WORD_SIZE
);
1453 else if (r_type
== R_MICROBLAZE_TEXTREL_64
1454 || r_type
== R_MICROBLAZE_TEXTREL_32_LO
)
1455 relocation
-= input_section
->output_section
->vma
;
1457 if (r_type
== R_MICROBLAZE_TEXTREL_32_LO
)
1458 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1459 contents
+ offset
+ endian
);
1463 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1464 contents
+ offset
+ endian
);
1465 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1466 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1472 if ((bfd_link_pic (info
)
1474 || (ELF_ST_VISIBILITY (h
->other
) == STV_DEFAULT
1475 && !resolved_to_zero
)
1476 || h
->root
.type
!= bfd_link_hash_undefweak
)
1477 && (!howto
->pc_relative
1481 || !h
->def_regular
))))
1482 || (!bfd_link_pic (info
)
1488 || h
->root
.type
== bfd_link_hash_undefweak
1489 || h
->root
.type
== bfd_link_hash_undefined
)))
1491 Elf_Internal_Rela outrel
;
1495 /* When generating a shared object, these relocations
1496 are copied into the output file to be resolved at run
1499 BFD_ASSERT (sreloc
!= NULL
);
1504 _bfd_elf_section_offset (output_bfd
, info
, input_section
,
1506 if (outrel
.r_offset
== (bfd_vma
) -1)
1508 else if (outrel
.r_offset
== (bfd_vma
) -2)
1510 outrel
.r_offset
+= (input_section
->output_section
->vma
1511 + input_section
->output_offset
);
1514 memset (&outrel
, 0, sizeof outrel
);
1515 /* h->dynindx may be -1 if the symbol was marked to
1518 && ((! info
->symbolic
&& h
->dynindx
!= -1)
1519 || !h
->def_regular
))
1521 BFD_ASSERT (h
->dynindx
!= -1);
1522 outrel
.r_info
= ELF32_R_INFO (h
->dynindx
, r_type
);
1523 outrel
.r_addend
= addend
;
1527 if (r_type
== R_MICROBLAZE_32
)
1529 outrel
.r_info
= ELF32_R_INFO (0, R_MICROBLAZE_REL
);
1530 outrel
.r_addend
= relocation
+ addend
;
1536 (_("%pB: probably compiled without -fPIC?"),
1538 bfd_set_error (bfd_error_bad_value
);
1543 loc
= sreloc
->contents
;
1544 loc
+= sreloc
->reloc_count
++ * sizeof (Elf32_External_Rela
);
1545 bfd_elf32_swap_reloca_out (output_bfd
, &outrel
, loc
);
1550 relocation
+= addend
;
1551 if (r_type
== R_MICROBLAZE_32
)
1552 bfd_put_32 (input_bfd
, relocation
, contents
+ offset
);
1555 if (r_type
== R_MICROBLAZE_64_PCREL
)
1556 relocation
-= (input_section
->output_section
->vma
1557 + input_section
->output_offset
1558 + offset
+ INST_WORD_SIZE
);
1559 else if (r_type
== R_MICROBLAZE_TEXTREL_64
1560 || r_type
== R_MICROBLAZE_TEXTREL_32_LO
)
1561 relocation
-= input_section
->output_section
->vma
;
1563 if (r_type
== R_MICROBLAZE_TEXTREL_32_LO
)
1565 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1566 contents
+ offset
+ endian
);
1570 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1571 contents
+ offset
+ endian
);
1572 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1573 contents
+ offset
+ endian
1582 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
1584 relocation
, addend
);
1591 if (r
!= bfd_reloc_ok
)
1593 /* FIXME: This should be generic enough to go in a utility. */
1597 name
= h
->root
.root
.string
;
1600 name
= (bfd_elf_string_from_elf_section
1601 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
1602 if (name
== NULL
|| *name
== '\0')
1603 name
= bfd_section_name (sec
);
1611 case bfd_reloc_overflow
:
1612 (*info
->callbacks
->reloc_overflow
)
1613 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
1614 (bfd_vma
) 0, input_bfd
, input_section
, offset
);
1617 case bfd_reloc_undefined
:
1618 (*info
->callbacks
->undefined_symbol
)
1619 (info
, name
, input_bfd
, input_section
, offset
, true);
1622 case bfd_reloc_outofrange
:
1623 errmsg
= _("internal error: out of range error");
1626 case bfd_reloc_notsupported
:
1627 errmsg
= _("internal error: unsupported relocation error");
1630 case bfd_reloc_dangerous
:
1631 errmsg
= _("internal error: dangerous error");
1635 errmsg
= _("internal error: unknown error");
1638 (*info
->callbacks
->warning
) (info
, errmsg
, name
, input_bfd
,
1639 input_section
, offset
);
1648 /* Calculate fixup value for reference. */
1651 calc_fixup (bfd_vma start
, bfd_vma size
, asection
*sec
)
1653 bfd_vma end
= start
+ size
;
1656 if (sec
== NULL
|| sec
->relax
== NULL
)
1659 /* Look for addr in relax table, total fixup value. */
1660 for (i
= 0; i
< sec
->relax_count
; i
++)
1662 if (end
<= sec
->relax
[i
].addr
)
1664 if ((end
!= start
) && (start
> sec
->relax
[i
].addr
))
1666 fixup
+= sec
->relax
[i
].size
;
1671 /* Read-modify-write into the bfd, an immediate value into appropriate fields of
1672 a 32-bit instruction. */
1674 microblaze_bfd_write_imm_value_32 (bfd
*abfd
, bfd_byte
*bfd_addr
, bfd_vma val
)
1676 unsigned long instr
= bfd_get_32 (abfd
, bfd_addr
);
1677 instr
&= ~0x0000ffff;
1678 instr
|= (val
& 0x0000ffff);
1679 bfd_put_32 (abfd
, instr
, bfd_addr
);
1682 /* Read-modify-write into the bfd, an immediate value into appropriate fields of
1683 two consecutive 32-bit instructions. */
1685 microblaze_bfd_write_imm_value_64 (bfd
*abfd
, bfd_byte
*bfd_addr
, bfd_vma val
)
1687 unsigned long instr_hi
;
1688 unsigned long instr_lo
;
1690 instr_hi
= bfd_get_32 (abfd
, bfd_addr
);
1691 instr_hi
&= ~0x0000ffff;
1692 instr_hi
|= ((val
>> 16) & 0x0000ffff);
1693 bfd_put_32 (abfd
, instr_hi
, bfd_addr
);
1695 instr_lo
= bfd_get_32 (abfd
, bfd_addr
+ INST_WORD_SIZE
);
1696 instr_lo
&= ~0x0000ffff;
1697 instr_lo
|= (val
& 0x0000ffff);
1698 bfd_put_32 (abfd
, instr_lo
, bfd_addr
+ INST_WORD_SIZE
);
1702 microblaze_elf_relax_section (bfd
*abfd
,
1704 struct bfd_link_info
*link_info
,
1707 Elf_Internal_Shdr
*symtab_hdr
;
1708 Elf_Internal_Rela
*internal_relocs
;
1709 Elf_Internal_Rela
*free_relocs
= NULL
;
1710 Elf_Internal_Rela
*irel
, *irelend
;
1711 bfd_byte
*contents
= NULL
;
1712 bfd_byte
*free_contents
= NULL
;
1717 struct elf_link_hash_entry
*sym_hash
;
1718 Elf_Internal_Sym
*isymbuf
, *isymend
;
1719 Elf_Internal_Sym
*isym
;
1724 /* We only do this once per section. We may be able to delete some code
1725 by running multiple passes, but it is not worth it. */
1728 /* Only do this for a text section. */
1729 if (bfd_link_relocatable (link_info
)
1730 || (sec
->flags
& SEC_RELOC
) == 0
1731 || (sec
->reloc_count
== 0)
1732 || (sec
->flags
& SEC_CODE
) == 0)
1735 BFD_ASSERT ((sec
->size
> 0) || (sec
->rawsize
> 0));
1737 /* If this is the first time we have been called for this section,
1738 initialize the cooked size. */
1740 sec
->size
= sec
->rawsize
;
1742 /* Get symbols for this section. */
1743 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
1744 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
1745 symcount
= symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
);
1746 if (isymbuf
== NULL
)
1747 isymbuf
= bfd_elf_get_elf_syms (abfd
, symtab_hdr
, symcount
,
1748 0, NULL
, NULL
, NULL
);
1749 BFD_ASSERT (isymbuf
!= NULL
);
1751 internal_relocs
= _bfd_elf_link_read_relocs (abfd
, sec
, NULL
, NULL
, link_info
->keep_memory
);
1752 if (internal_relocs
== NULL
)
1754 if (! link_info
->keep_memory
)
1755 free_relocs
= internal_relocs
;
1757 sec
->relax
= (struct relax_table
*) bfd_malloc ((sec
->reloc_count
+ 1)
1758 * sizeof (struct relax_table
));
1759 if (sec
->relax
== NULL
)
1761 sec
->relax_count
= 0;
1763 irelend
= internal_relocs
+ sec
->reloc_count
;
1765 for (irel
= internal_relocs
; irel
< irelend
; irel
++, rel_count
++)
1768 if ((ELF32_R_TYPE (irel
->r_info
) != (int) R_MICROBLAZE_64_PCREL
)
1769 && (ELF32_R_TYPE (irel
->r_info
) != (int) R_MICROBLAZE_64
)
1770 && (ELF32_R_TYPE (irel
->r_info
) != (int) R_MICROBLAZE_TEXTREL_64
))
1771 continue; /* Can't delete this reloc. */
1773 /* Get the section contents. */
1774 if (contents
== NULL
)
1776 if (elf_section_data (sec
)->this_hdr
.contents
!= NULL
)
1777 contents
= elf_section_data (sec
)->this_hdr
.contents
;
1780 contents
= (bfd_byte
*) bfd_malloc (sec
->size
);
1781 if (contents
== NULL
)
1783 free_contents
= contents
;
1785 if (!bfd_get_section_contents (abfd
, sec
, contents
,
1786 (file_ptr
) 0, sec
->size
))
1788 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1792 /* Get the value of the symbol referred to by the reloc. */
1793 if (ELF32_R_SYM (irel
->r_info
) < symtab_hdr
->sh_info
)
1795 /* A local symbol. */
1798 isym
= isymbuf
+ ELF32_R_SYM (irel
->r_info
);
1799 if (isym
->st_shndx
== SHN_UNDEF
)
1800 sym_sec
= bfd_und_section_ptr
;
1801 else if (isym
->st_shndx
== SHN_ABS
)
1802 sym_sec
= bfd_abs_section_ptr
;
1803 else if (isym
->st_shndx
== SHN_COMMON
)
1804 sym_sec
= bfd_com_section_ptr
;
1806 sym_sec
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
1808 symval
= _bfd_elf_rela_local_sym (abfd
, isym
, &sym_sec
, irel
);
1813 struct elf_link_hash_entry
*h
;
1815 indx
= ELF32_R_SYM (irel
->r_info
) - symtab_hdr
->sh_info
;
1816 h
= elf_sym_hashes (abfd
)[indx
];
1817 BFD_ASSERT (h
!= NULL
);
1819 if (h
->root
.type
!= bfd_link_hash_defined
1820 && h
->root
.type
!= bfd_link_hash_defweak
)
1821 /* This appears to be a reference to an undefined
1822 symbol. Just ignore it--it will be caught by the
1823 regular reloc processing. */
1826 symval
= (h
->root
.u
.def
.value
1827 + h
->root
.u
.def
.section
->output_section
->vma
1828 + h
->root
.u
.def
.section
->output_offset
);
1831 /* If this is a PC-relative reloc, subtract the instr offset from
1832 the symbol value. */
1833 if (ELF32_R_TYPE (irel
->r_info
) == (int) R_MICROBLAZE_64_PCREL
)
1835 symval
= symval
+ irel
->r_addend
1837 + sec
->output_section
->vma
1838 + sec
->output_offset
);
1840 else if (ELF32_R_TYPE (irel
->r_info
) == (int) R_MICROBLAZE_TEXTREL_64
)
1842 symval
= symval
+ irel
->r_addend
- (sec
->output_section
->vma
);
1845 symval
+= irel
->r_addend
;
1847 if ((symval
& 0xffff8000) == 0
1848 || (symval
& 0xffff8000) == 0xffff8000)
1850 /* We can delete this instruction. */
1851 sec
->relax
[sec
->relax_count
].addr
= irel
->r_offset
;
1852 sec
->relax
[sec
->relax_count
].size
= INST_WORD_SIZE
;
1855 /* Rewrite relocation type. */
1856 switch ((enum elf_microblaze_reloc_type
) ELF32_R_TYPE (irel
->r_info
))
1858 case R_MICROBLAZE_64_PCREL
:
1859 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1860 (int) R_MICROBLAZE_32_PCREL_LO
);
1862 case R_MICROBLAZE_64
:
1863 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1864 (int) R_MICROBLAZE_32_LO
);
1866 case R_MICROBLAZE_TEXTREL_64
:
1867 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1868 (int) R_MICROBLAZE_TEXTREL_32_LO
);
1871 /* Cannot happen. */
1875 } /* Loop through all relocations. */
1877 /* Loop through the relocs again, and see if anything needs to change. */
1878 if (sec
->relax_count
> 0)
1880 shndx
= _bfd_elf_section_from_bfd_section (abfd
, sec
);
1882 sec
->relax
[sec
->relax_count
].addr
= sec
->size
;
1884 for (irel
= internal_relocs
; irel
< irelend
; irel
++, rel_count
++)
1888 /* Get the new reloc address. */
1889 nraddr
= irel
->r_offset
- calc_fixup (irel
->r_offset
, 0, sec
);
1890 switch ((enum elf_microblaze_reloc_type
) ELF32_R_TYPE (irel
->r_info
))
1894 case R_MICROBLAZE_64_PCREL
:
1896 case R_MICROBLAZE_TEXTREL_64
:
1897 case R_MICROBLAZE_TEXTREL_32_LO
:
1898 case R_MICROBLAZE_64
:
1899 case R_MICROBLAZE_32_LO
:
1900 /* If this reloc is against a symbol defined in this
1901 section, we must check the addend to see it will put the value in
1902 range to be adjusted, and hence must be changed. */
1903 if (ELF32_R_SYM (irel
->r_info
) < symtab_hdr
->sh_info
)
1905 isym
= isymbuf
+ ELF32_R_SYM (irel
->r_info
);
1906 /* Only handle relocs against .text. */
1907 if (isym
->st_shndx
== shndx
1908 && ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
)
1909 irel
->r_addend
-= calc_fixup (irel
->r_addend
, 0, sec
);
1912 case R_MICROBLAZE_NONE
:
1914 /* This was a PC-relative instruction that was
1915 completely resolved. */
1917 bfd_vma target_address
;
1918 target_address
= irel
->r_addend
+ irel
->r_offset
;
1919 sfix
= calc_fixup (irel
->r_offset
, 0, sec
);
1920 efix
= calc_fixup (target_address
, 0, sec
);
1921 irel
->r_addend
-= (efix
- sfix
);
1922 /* Should use HOWTO. */
1923 microblaze_bfd_write_imm_value_32 (abfd
, contents
+ irel
->r_offset
,
1927 case R_MICROBLAZE_64_NONE
:
1929 /* This was a PC-relative 64-bit instruction that was
1930 completely resolved. */
1932 bfd_vma target_address
;
1933 target_address
= irel
->r_addend
+ irel
->r_offset
+ INST_WORD_SIZE
;
1934 sfix
= calc_fixup (irel
->r_offset
+ INST_WORD_SIZE
, 0, sec
);
1935 efix
= calc_fixup (target_address
, 0, sec
);
1936 irel
->r_addend
-= (efix
- sfix
);
1937 microblaze_bfd_write_imm_value_32 (abfd
, contents
+ irel
->r_offset
1938 + INST_WORD_SIZE
, irel
->r_addend
);
1942 irel
->r_offset
= nraddr
;
1943 } /* Change all relocs in this section. */
1945 /* Look through all other sections. */
1946 for (o
= abfd
->sections
; o
!= NULL
; o
= o
->next
)
1948 Elf_Internal_Rela
*irelocs
;
1949 Elf_Internal_Rela
*irelscan
, *irelscanend
;
1950 bfd_byte
*ocontents
;
1953 || (o
->flags
& SEC_RELOC
) == 0
1954 || o
->reloc_count
== 0)
1957 /* We always cache the relocs. Perhaps, if info->keep_memory is
1958 FALSE, we should free them, if we are permitted to. */
1960 irelocs
= _bfd_elf_link_read_relocs (abfd
, o
, NULL
, NULL
, true);
1961 if (irelocs
== NULL
)
1965 irelscanend
= irelocs
+ o
->reloc_count
;
1966 for (irelscan
= irelocs
; irelscan
< irelscanend
; irelscan
++)
1968 if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_32
)
1970 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
1972 /* Look at the reloc only if the value has been resolved. */
1973 if (isym
->st_shndx
== shndx
1974 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
1976 if (ocontents
== NULL
)
1978 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
1979 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
1982 /* We always cache the section contents.
1983 Perhaps, if info->keep_memory is FALSE, we
1984 should free them, if we are permitted to. */
1985 if (o
->rawsize
== 0)
1986 o
->rawsize
= o
->size
;
1987 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
1988 if (ocontents
== NULL
)
1990 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
1994 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
1998 irelscan
->r_addend
-= calc_fixup (irelscan
->r_addend
, 0, sec
);
2000 else if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_32_SYM_OP_SYM
)
2002 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2004 /* Look at the reloc only if the value has been resolved. */
2005 if (ocontents
== NULL
)
2007 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2008 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2011 /* We always cache the section contents.
2012 Perhaps, if info->keep_memory is FALSE, we
2013 should free them, if we are permitted to. */
2015 if (o
->rawsize
== 0)
2016 o
->rawsize
= o
->size
;
2017 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2018 if (ocontents
== NULL
)
2020 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2024 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2027 irelscan
->r_addend
-= calc_fixup (irel
->r_addend
2033 else if ((ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_32_PCREL_LO
)
2034 || (ELF32_R_TYPE (irelscan
->r_info
)
2035 == (int) R_MICROBLAZE_32_LO
)
2036 || (ELF32_R_TYPE (irelscan
->r_info
)
2037 == (int) R_MICROBLAZE_TEXTREL_32_LO
))
2039 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2041 /* Look at the reloc only if the value has been resolved. */
2042 if (isym
->st_shndx
== shndx
2043 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
2046 bfd_vma target_address
;
2048 if (ocontents
== NULL
)
2050 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2051 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2054 /* We always cache the section contents.
2055 Perhaps, if info->keep_memory is FALSE, we
2056 should free them, if we are permitted to. */
2057 if (o
->rawsize
== 0)
2058 o
->rawsize
= o
->size
;
2059 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2060 if (ocontents
== NULL
)
2062 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2066 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2070 unsigned long instr
= bfd_get_32 (abfd
, ocontents
+ irelscan
->r_offset
);
2071 immediate
= instr
& 0x0000ffff;
2072 target_address
= immediate
;
2073 offset
= calc_fixup (target_address
, 0, sec
);
2074 immediate
-= offset
;
2075 irelscan
->r_addend
-= offset
;
2076 microblaze_bfd_write_imm_value_32 (abfd
, ocontents
+ irelscan
->r_offset
,
2077 irelscan
->r_addend
);
2081 if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_64
2082 || (ELF32_R_TYPE (irelscan
->r_info
)
2083 == (int) R_MICROBLAZE_TEXTREL_64
))
2085 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2087 /* Look at the reloc only if the value has been resolved. */
2088 if (isym
->st_shndx
== shndx
2089 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
2093 if (ocontents
== NULL
)
2095 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2096 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2099 /* We always cache the section contents.
2100 Perhaps, if info->keep_memory is FALSE, we
2101 should free them, if we are permitted to. */
2103 if (o
->rawsize
== 0)
2104 o
->rawsize
= o
->size
;
2105 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2106 if (ocontents
== NULL
)
2108 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2112 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2115 unsigned long instr_hi
= bfd_get_32 (abfd
, ocontents
2116 + irelscan
->r_offset
);
2117 unsigned long instr_lo
= bfd_get_32 (abfd
, ocontents
2118 + irelscan
->r_offset
2120 immediate
= (instr_hi
& 0x0000ffff) << 16;
2121 immediate
|= (instr_lo
& 0x0000ffff);
2122 offset
= calc_fixup (irelscan
->r_addend
, 0, sec
);
2123 immediate
-= offset
;
2124 irelscan
->r_addend
-= offset
;
2127 else if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_64_PCREL
)
2129 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2131 /* Look at the reloc only if the value has been resolved. */
2132 if (isym
->st_shndx
== shndx
2133 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
2136 bfd_vma target_address
;
2138 if (ocontents
== NULL
)
2140 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2141 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2144 /* We always cache the section contents.
2145 Perhaps, if info->keep_memory is FALSE, we
2146 should free them, if we are permitted to. */
2147 if (o
->rawsize
== 0)
2148 o
->rawsize
= o
->size
;
2149 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2150 if (ocontents
== NULL
)
2152 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2156 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2159 unsigned long instr_hi
= bfd_get_32 (abfd
, ocontents
2160 + irelscan
->r_offset
);
2161 unsigned long instr_lo
= bfd_get_32 (abfd
, ocontents
2162 + irelscan
->r_offset
2164 immediate
= (instr_hi
& 0x0000ffff) << 16;
2165 immediate
|= (instr_lo
& 0x0000ffff);
2166 target_address
= immediate
;
2167 offset
= calc_fixup (target_address
, 0, sec
);
2168 immediate
-= offset
;
2169 irelscan
->r_addend
-= offset
;
2170 microblaze_bfd_write_imm_value_64 (abfd
, ocontents
2171 + irelscan
->r_offset
, immediate
);
2177 /* Adjust the local symbols defined in this section. */
2178 isymend
= isymbuf
+ symtab_hdr
->sh_info
;
2179 for (isym
= isymbuf
; isym
< isymend
; isym
++)
2181 if (isym
->st_shndx
== shndx
)
2183 isym
->st_value
-= calc_fixup (isym
->st_value
, 0, sec
);
2185 isym
->st_size
-= calc_fixup (isym
->st_value
, isym
->st_size
, sec
);
2189 /* Now adjust the global symbols defined in this section. */
2190 isym
= isymbuf
+ symtab_hdr
->sh_info
;
2191 symcount
= (symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
)) - symtab_hdr
->sh_info
;
2192 for (sym_index
= 0; sym_index
< symcount
; sym_index
++)
2194 sym_hash
= elf_sym_hashes (abfd
)[sym_index
];
2195 if ((sym_hash
->root
.type
== bfd_link_hash_defined
2196 || sym_hash
->root
.type
== bfd_link_hash_defweak
)
2197 && sym_hash
->root
.u
.def
.section
== sec
)
2199 sym_hash
->root
.u
.def
.value
-= calc_fixup (sym_hash
->root
.u
.def
.value
,
2202 sym_hash
->size
-= calc_fixup (sym_hash
->root
.u
.def
.value
,
2203 sym_hash
->size
, sec
);
2207 /* Physically move the code and change the cooked size. */
2208 dest
= sec
->relax
[0].addr
;
2209 for (i
= 0; i
< sec
->relax_count
; i
++)
2212 src
= sec
->relax
[i
].addr
+ sec
->relax
[i
].size
;
2213 len
= sec
->relax
[i
+1].addr
- sec
->relax
[i
].addr
- sec
->relax
[i
].size
;
2215 memmove (contents
+ dest
, contents
+ src
, len
);
2216 sec
->size
-= sec
->relax
[i
].size
;
2220 elf_section_data (sec
)->relocs
= internal_relocs
;
2223 elf_section_data (sec
)->this_hdr
.contents
= contents
;
2224 free_contents
= NULL
;
2226 symtab_hdr
->contents
= (bfd_byte
*) isymbuf
;
2232 if (free_contents
!= NULL
)
2234 if (!link_info
->keep_memory
)
2235 free (free_contents
);
2237 /* Cache the section contents for elf_link_input_bfd. */
2238 elf_section_data (sec
)->this_hdr
.contents
= contents
;
2239 free_contents
= NULL
;
2242 if (sec
->relax_count
== 0)
2254 free (free_contents
);
2257 sec
->relax_count
= 0;
2261 /* Return the section that should be marked against GC for a given
2265 microblaze_elf_gc_mark_hook (asection
*sec
,
2266 struct bfd_link_info
* info
,
2267 Elf_Internal_Rela
* rel
,
2268 struct elf_link_hash_entry
* h
,
2269 Elf_Internal_Sym
* sym
)
2272 switch (ELF32_R_TYPE (rel
->r_info
))
2274 case R_MICROBLAZE_GNU_VTINHERIT
:
2275 case R_MICROBLAZE_GNU_VTENTRY
:
2279 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
2284 #define PLT_ENTRY_SIZE 16
2286 #define PLT_ENTRY_WORD_0 0xb0000000 /* "imm 0". */
2287 #define PLT_ENTRY_WORD_1 0xe9940000 /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT. */
2288 #define PLT_ENTRY_WORD_1_NOPIC 0xe9800000 /* "lwi r12,r0,0" - non-PIC object. */
2289 #define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
2290 #define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
2293 update_local_sym_info (bfd
*abfd
,
2294 Elf_Internal_Shdr
*symtab_hdr
,
2295 unsigned long r_symndx
,
2296 unsigned int tls_type
)
2298 bfd_signed_vma
*local_got_refcounts
= elf_local_got_refcounts (abfd
);
2299 unsigned char *local_got_tls_masks
;
2301 if (local_got_refcounts
== NULL
)
2303 bfd_size_type size
= symtab_hdr
->sh_info
;
2305 size
*= (sizeof (*local_got_refcounts
) + sizeof (*local_got_tls_masks
));
2306 local_got_refcounts
= bfd_zalloc (abfd
, size
);
2307 if (local_got_refcounts
== NULL
)
2309 elf_local_got_refcounts (abfd
) = local_got_refcounts
;
2312 local_got_tls_masks
=
2313 (unsigned char *) (local_got_refcounts
+ symtab_hdr
->sh_info
);
2314 local_got_tls_masks
[r_symndx
] |= tls_type
;
2315 local_got_refcounts
[r_symndx
] += 1;
2319 /* Look through the relocs for a section during the first phase. */
2322 microblaze_elf_check_relocs (bfd
* abfd
,
2323 struct bfd_link_info
* info
,
2325 const Elf_Internal_Rela
* relocs
)
2327 Elf_Internal_Shdr
* symtab_hdr
;
2328 struct elf_link_hash_entry
** sym_hashes
;
2329 struct elf_link_hash_entry
** sym_hashes_end
;
2330 const Elf_Internal_Rela
* rel
;
2331 const Elf_Internal_Rela
* rel_end
;
2332 struct elf32_mb_link_hash_table
*htab
;
2333 asection
*sreloc
= NULL
;
2335 if (bfd_link_relocatable (info
))
2338 htab
= elf32_mb_hash_table (info
);
2342 symtab_hdr
= & elf_tdata (abfd
)->symtab_hdr
;
2343 sym_hashes
= elf_sym_hashes (abfd
);
2344 sym_hashes_end
= sym_hashes
+ symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
);
2345 if (!elf_bad_symtab (abfd
))
2346 sym_hashes_end
-= symtab_hdr
->sh_info
;
2348 rel_end
= relocs
+ sec
->reloc_count
;
2350 for (rel
= relocs
; rel
< rel_end
; rel
++)
2352 unsigned int r_type
;
2353 struct elf_link_hash_entry
* h
;
2354 unsigned long r_symndx
;
2355 unsigned char tls_type
= 0;
2357 r_symndx
= ELF32_R_SYM (rel
->r_info
);
2358 r_type
= ELF32_R_TYPE (rel
->r_info
);
2360 if (r_symndx
< symtab_hdr
->sh_info
)
2364 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
2365 while (h
->root
.type
== bfd_link_hash_indirect
2366 || h
->root
.type
== bfd_link_hash_warning
)
2367 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
2372 /* This relocation describes the C++ object vtable hierarchy.
2373 Reconstruct it for later use during GC. */
2374 case R_MICROBLAZE_GNU_VTINHERIT
:
2375 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
2379 /* This relocation describes which C++ vtable entries are actually
2380 used. Record for later use during GC. */
2381 case R_MICROBLAZE_GNU_VTENTRY
:
2382 if (!bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
2386 /* This relocation requires .plt entry. */
2387 case R_MICROBLAZE_PLT_64
:
2391 h
->plt
.refcount
+= 1;
2395 /* This relocation requires .got entry. */
2396 case R_MICROBLAZE_TLSGD
:
2397 tls_type
|= (TLS_TLS
| TLS_GD
);
2399 case R_MICROBLAZE_TLSLD
:
2400 tls_type
|= (TLS_TLS
| TLS_LD
);
2403 sec
->has_tls_reloc
= 1;
2405 case R_MICROBLAZE_GOT_64
:
2406 if (htab
->elf
.sgot
== NULL
)
2408 if (htab
->elf
.dynobj
== NULL
)
2409 htab
->elf
.dynobj
= abfd
;
2410 if (!_bfd_elf_create_got_section (htab
->elf
.dynobj
, info
))
2415 h
->got
.refcount
+= 1;
2416 elf32_mb_hash_entry (h
)->tls_mask
|= tls_type
;
2420 if (! update_local_sym_info(abfd
, symtab_hdr
, r_symndx
, tls_type
) )
2425 case R_MICROBLAZE_GOTOFF_64
:
2426 case R_MICROBLAZE_GOTOFF_32
:
2427 if (htab
->elf
.sgot
== NULL
)
2429 if (htab
->elf
.dynobj
== NULL
)
2430 htab
->elf
.dynobj
= abfd
;
2431 if (!_bfd_elf_create_got_section (htab
->elf
.dynobj
, info
))
2436 case R_MICROBLAZE_64
:
2437 case R_MICROBLAZE_64_PCREL
:
2438 case R_MICROBLAZE_32
:
2440 if (h
!= NULL
&& !bfd_link_pic (info
))
2442 /* we may need a copy reloc. */
2445 /* we may also need a .plt entry. */
2446 h
->plt
.refcount
+= 1;
2447 if (ELF32_R_TYPE (rel
->r_info
) != R_MICROBLAZE_64_PCREL
)
2448 h
->pointer_equality_needed
= 1;
2452 /* If we are creating a shared library, and this is a reloc
2453 against a global symbol, or a non PC relative reloc
2454 against a local symbol, then we need to copy the reloc
2455 into the shared library. However, if we are linking with
2456 -Bsymbolic, we do not need to copy a reloc against a
2457 global symbol which is defined in an object we are
2458 including in the link (i.e., DEF_REGULAR is set). At
2459 this point we have not seen all the input files, so it is
2460 possible that DEF_REGULAR is not set now but will be set
2461 later (it is never cleared). In case of a weak definition,
2462 DEF_REGULAR may be cleared later by a strong definition in
2463 a shared library. We account for that possibility below by
2464 storing information in the relocs_copied field of the hash
2465 table entry. A similar situation occurs when creating
2466 shared libraries and symbol visibility changes render the
2469 If on the other hand, we are creating an executable, we
2470 may need to keep relocations for symbols satisfied by a
2471 dynamic library if we manage to avoid copy relocs for the
2474 if ((bfd_link_pic (info
)
2475 && (sec
->flags
& SEC_ALLOC
) != 0
2476 && (r_type
!= R_MICROBLAZE_64_PCREL
2478 && (! info
->symbolic
2479 || h
->root
.type
== bfd_link_hash_defweak
2480 || !h
->def_regular
))))
2481 || (!bfd_link_pic (info
)
2482 && (sec
->flags
& SEC_ALLOC
) != 0
2484 && (h
->root
.type
== bfd_link_hash_defweak
2485 || !h
->def_regular
)))
2487 struct elf_dyn_relocs
*p
;
2488 struct elf_dyn_relocs
**head
;
2490 /* When creating a shared object, we must copy these
2491 relocs into the output file. We create a reloc
2492 section in dynobj and make room for the reloc. */
2498 if (htab
->elf
.dynobj
== NULL
)
2499 htab
->elf
.dynobj
= abfd
;
2500 dynobj
= htab
->elf
.dynobj
;
2502 sreloc
= _bfd_elf_make_dynamic_reloc_section (sec
, dynobj
,
2508 /* If this is a global symbol, we count the number of
2509 relocations we need for this symbol. */
2511 head
= &h
->dyn_relocs
;
2514 /* Track dynamic relocs needed for local syms too.
2515 We really need local syms available to do this
2519 Elf_Internal_Sym
*isym
;
2522 isym
= bfd_sym_from_r_symndx (&htab
->elf
.sym_cache
,
2527 s
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
2531 vpp
= &elf_section_data (s
)->local_dynrel
;
2532 head
= (struct elf_dyn_relocs
**) vpp
;
2536 if (p
== NULL
|| p
->sec
!= sec
)
2538 size_t amt
= sizeof *p
;
2539 p
= ((struct elf_dyn_relocs
*)
2540 bfd_alloc (htab
->elf
.dynobj
, amt
));
2551 if (r_type
== R_MICROBLAZE_64_PCREL
)
2562 /* Copy the extra info we tack onto an elf_link_hash_entry. */
2565 microblaze_elf_copy_indirect_symbol (struct bfd_link_info
*info
,
2566 struct elf_link_hash_entry
*dir
,
2567 struct elf_link_hash_entry
*ind
)
2569 struct elf32_mb_link_hash_entry
*edir
, *eind
;
2571 edir
= (struct elf32_mb_link_hash_entry
*) dir
;
2572 eind
= (struct elf32_mb_link_hash_entry
*) ind
;
2574 edir
->tls_mask
|= eind
->tls_mask
;
2576 _bfd_elf_link_hash_copy_indirect (info
, dir
, ind
);
2580 microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info
*info
,
2581 struct elf_link_hash_entry
*h
)
2583 struct elf32_mb_link_hash_table
*htab
;
2585 unsigned int power_of_two
;
2587 htab
= elf32_mb_hash_table (info
);
2591 /* If this is a function, put it in the procedure linkage table. We
2592 will fill in the contents of the procedure linkage table later,
2593 when we know the address of the .got section. */
2594 if (h
->type
== STT_FUNC
2597 if (h
->plt
.refcount
<= 0
2598 || SYMBOL_CALLS_LOCAL (info
, h
)
2599 || (ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
2600 && h
->root
.type
== bfd_link_hash_undefweak
))
2602 /* This case can occur if we saw a PLT reloc in an input
2603 file, but the symbol was never referred to by a dynamic
2604 object, or if all references were garbage collected. In
2605 such a case, we don't actually need to build a procedure
2606 linkage table, and we can just do a PC32 reloc instead. */
2607 h
->plt
.offset
= (bfd_vma
) -1;
2614 /* It's possible that we incorrectly decided a .plt reloc was
2615 needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
2616 check_relocs. We can't decide accurately between function and
2617 non-function syms in check-relocs; Objects loaded later in
2618 the link may change h->type. So fix it now. */
2619 h
->plt
.offset
= (bfd_vma
) -1;
2621 /* If this is a weak symbol, and there is a real definition, the
2622 processor independent code will have arranged for us to see the
2623 real definition first, and we can just use the same value. */
2624 if (h
->is_weakalias
)
2626 struct elf_link_hash_entry
*def
= weakdef (h
);
2627 BFD_ASSERT (def
->root
.type
== bfd_link_hash_defined
);
2628 h
->root
.u
.def
.section
= def
->root
.u
.def
.section
;
2629 h
->root
.u
.def
.value
= def
->root
.u
.def
.value
;
2633 /* This is a reference to a symbol defined by a dynamic object which
2634 is not a function. */
2636 /* If we are creating a shared library, we must presume that the
2637 only references to the symbol are via the global offset table.
2638 For such cases we need not do anything here; the relocations will
2639 be handled correctly by relocate_section. */
2640 if (bfd_link_pic (info
))
2643 /* If there are no references to this symbol that do not use the
2644 GOT, we don't need to generate a copy reloc. */
2645 if (!h
->non_got_ref
)
2648 /* If -z nocopyreloc was given, we won't generate them either. */
2649 if (info
->nocopyreloc
)
2655 /* If we don't find any dynamic relocs in read-only sections, then
2656 we'll be keeping the dynamic relocs and avoiding the copy reloc. */
2657 if (!_bfd_elf_readonly_dynrelocs (h
))
2663 /* We must allocate the symbol in our .dynbss section, which will
2664 become part of the .bss section of the executable. There will be
2665 an entry for this symbol in the .dynsym section. The dynamic
2666 object will contain position independent code, so all references
2667 from the dynamic object to this symbol will go through the global
2668 offset table. The dynamic linker will use the .dynsym entry to
2669 determine the address it must put in the global offset table, so
2670 both the dynamic object and the regular object will refer to the
2671 same memory location for the variable. */
2673 /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
2674 to copy the initial value out of the dynamic object and into the
2675 runtime process image. */
2676 if ((h
->root
.u
.def
.section
->flags
& SEC_READONLY
) != 0)
2678 s
= htab
->elf
.sdynrelro
;
2679 srel
= htab
->elf
.sreldynrelro
;
2683 s
= htab
->elf
.sdynbss
;
2684 srel
= htab
->elf
.srelbss
;
2686 if ((h
->root
.u
.def
.section
->flags
& SEC_ALLOC
) != 0)
2688 srel
->size
+= sizeof (Elf32_External_Rela
);
2692 /* We need to figure out the alignment required for this symbol. I
2693 have no idea how ELF linkers handle this. */
2694 power_of_two
= bfd_log2 (h
->size
);
2695 if (power_of_two
> 3)
2698 /* Apply the required alignment. */
2699 s
->size
= BFD_ALIGN (s
->size
, (bfd_size_type
) (1 << power_of_two
));
2700 if (power_of_two
> s
->alignment_power
)
2702 if (!bfd_set_section_alignment (s
, power_of_two
))
2706 /* Define the symbol as being at this point in the section. */
2707 h
->root
.u
.def
.section
= s
;
2708 h
->root
.u
.def
.value
= s
->size
;
2710 /* Increment the section size to make room for the symbol. */
2715 /* Allocate space in .plt, .got and associated reloc sections for
2719 allocate_dynrelocs (struct elf_link_hash_entry
*h
, void * dat
)
2721 struct bfd_link_info
*info
;
2722 struct elf32_mb_link_hash_table
*htab
;
2723 struct elf32_mb_link_hash_entry
*eh
;
2724 struct elf_dyn_relocs
*p
;
2726 if (h
->root
.type
== bfd_link_hash_indirect
)
2729 info
= (struct bfd_link_info
*) dat
;
2730 htab
= elf32_mb_hash_table (info
);
2734 if (htab
->elf
.dynamic_sections_created
2735 && h
->plt
.refcount
> 0)
2737 /* Make sure this symbol is output as a dynamic symbol.
2738 Undefined weak syms won't yet be marked as dynamic. */
2739 if (h
->dynindx
== -1
2740 && !h
->forced_local
)
2742 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2746 if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info
), h
))
2748 asection
*s
= htab
->elf
.splt
;
2750 /* The first entry in .plt is reserved. */
2752 s
->size
= PLT_ENTRY_SIZE
;
2754 h
->plt
.offset
= s
->size
;
2756 /* If this symbol is not defined in a regular file, and we are
2757 not generating a shared library, then set the symbol to this
2758 location in the .plt. This is required to make function
2759 pointers compare as equal between the normal executable and
2760 the shared library. */
2761 if (! bfd_link_pic (info
)
2764 h
->root
.u
.def
.section
= s
;
2765 h
->root
.u
.def
.value
= h
->plt
.offset
;
2768 /* Make room for this entry. */
2769 s
->size
+= PLT_ENTRY_SIZE
;
2771 /* We also need to make an entry in the .got.plt section, which
2772 will be placed in the .got section by the linker script. */
2773 htab
->elf
.sgotplt
->size
+= 4;
2775 /* We also need to make an entry in the .rel.plt section. */
2776 htab
->elf
.srelplt
->size
+= sizeof (Elf32_External_Rela
);
2780 h
->plt
.offset
= (bfd_vma
) -1;
2786 h
->plt
.offset
= (bfd_vma
) -1;
2790 eh
= (struct elf32_mb_link_hash_entry
*) h
;
2791 if (h
->got
.refcount
> 0)
2796 /* Make sure this symbol is output as a dynamic symbol.
2797 Undefined weak syms won't yet be marked as dynamic. */
2798 if (h
->dynindx
== -1
2799 && !h
->forced_local
)
2801 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2806 if ((eh
->tls_mask
& TLS_TLS
) != 0)
2808 /* Handle TLS Symbol */
2809 if ((eh
->tls_mask
& TLS_LD
) != 0)
2811 if (!eh
->elf
.def_dynamic
)
2812 /* We'll just use htab->tlsld_got.offset. This should
2813 always be the case. It's a little odd if we have
2814 a local dynamic reloc against a non-local symbol. */
2815 htab
->tlsld_got
.refcount
+= 1;
2819 if ((eh
->tls_mask
& TLS_GD
) != 0)
2824 /* Regular (non-TLS) symbol */
2829 h
->got
.offset
= (bfd_vma
) -1;
2834 h
->got
.offset
= s
->size
;
2836 htab
->elf
.srelgot
->size
+= need
* (sizeof (Elf32_External_Rela
) / 4);
2840 h
->got
.offset
= (bfd_vma
) -1;
2842 if (h
->dyn_relocs
== NULL
)
2845 /* In the shared -Bsymbolic case, discard space allocated for
2846 dynamic pc-relative relocs against symbols which turn out to be
2847 defined in regular objects. For the normal shared case, discard
2848 space for pc-relative relocs that have become local due to symbol
2849 visibility changes. */
2851 if (bfd_link_pic (info
))
2857 struct elf_dyn_relocs
**pp
;
2859 for (pp
= &h
->dyn_relocs
; (p
= *pp
) != NULL
; )
2861 p
->count
-= p
->pc_count
;
2869 else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
2870 h
->dyn_relocs
= NULL
;
2874 /* For the non-shared case, discard space for relocs against
2875 symbols which turn out to need copy relocs or are not
2881 || (htab
->elf
.dynamic_sections_created
2882 && (h
->root
.type
== bfd_link_hash_undefweak
2883 || h
->root
.type
== bfd_link_hash_undefined
))))
2885 /* Make sure this symbol is output as a dynamic symbol.
2886 Undefined weak syms won't yet be marked as dynamic. */
2887 if (h
->dynindx
== -1
2888 && !h
->forced_local
)
2890 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2894 /* If that succeeded, we know we'll be keeping all the
2896 if (h
->dynindx
!= -1)
2900 h
->dyn_relocs
= NULL
;
2905 /* Finally, allocate space. */
2906 for (p
= h
->dyn_relocs
; p
!= NULL
; p
= p
->next
)
2908 asection
*sreloc
= elf_section_data (p
->sec
)->sreloc
;
2909 sreloc
->size
+= p
->count
* sizeof (Elf32_External_Rela
);
2915 /* Set the sizes of the dynamic sections. */
2918 microblaze_elf_size_dynamic_sections (bfd
*output_bfd ATTRIBUTE_UNUSED
,
2919 struct bfd_link_info
*info
)
2921 struct elf32_mb_link_hash_table
*htab
;
2926 htab
= elf32_mb_hash_table (info
);
2930 dynobj
= htab
->elf
.dynobj
;
2931 BFD_ASSERT (dynobj
!= NULL
);
2933 /* Set up .got offsets for local syms, and space for local dynamic
2935 for (ibfd
= info
->input_bfds
; ibfd
!= NULL
; ibfd
= ibfd
->link
.next
)
2937 bfd_signed_vma
*local_got
;
2938 bfd_signed_vma
*end_local_got
;
2939 bfd_size_type locsymcount
;
2940 Elf_Internal_Shdr
*symtab_hdr
;
2941 unsigned char *lgot_masks
;
2944 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
)
2947 for (s
= ibfd
->sections
; s
!= NULL
; s
= s
->next
)
2949 struct elf_dyn_relocs
*p
;
2951 for (p
= ((struct elf_dyn_relocs
*)
2952 elf_section_data (s
)->local_dynrel
);
2956 if (!bfd_is_abs_section (p
->sec
)
2957 && bfd_is_abs_section (p
->sec
->output_section
))
2959 /* Input section has been discarded, either because
2960 it is a copy of a linkonce section or due to
2961 linker script /DISCARD/, so we'll be discarding
2964 else if (p
->count
!= 0)
2966 srel
= elf_section_data (p
->sec
)->sreloc
;
2967 srel
->size
+= p
->count
* sizeof (Elf32_External_Rela
);
2968 if ((p
->sec
->output_section
->flags
& SEC_READONLY
) != 0)
2969 info
->flags
|= DF_TEXTREL
;
2974 local_got
= elf_local_got_refcounts (ibfd
);
2978 symtab_hdr
= &elf_tdata (ibfd
)->symtab_hdr
;
2979 locsymcount
= symtab_hdr
->sh_info
;
2980 end_local_got
= local_got
+ locsymcount
;
2981 lgot_masks
= (unsigned char *) end_local_got
;
2983 srel
= htab
->elf
.srelgot
;
2985 for (; local_got
< end_local_got
; ++local_got
, ++lgot_masks
)
2989 unsigned int need
= 0;
2990 if ((*lgot_masks
& TLS_TLS
) != 0)
2992 if ((*lgot_masks
& TLS_GD
) != 0)
2994 if ((*lgot_masks
& TLS_LD
) != 0)
2995 htab
->tlsld_got
.refcount
+= 1;
3002 *local_got
= (bfd_vma
) -1;
3006 *local_got
= s
->size
;
3008 if (bfd_link_pic (info
))
3009 srel
->size
+= need
* (sizeof (Elf32_External_Rela
) / 4);
3013 *local_got
= (bfd_vma
) -1;
3017 /* Allocate global sym .plt and .got entries, and space for global
3018 sym dynamic relocs. */
3019 elf_link_hash_traverse (elf_hash_table (info
), allocate_dynrelocs
, info
);
3021 if (htab
->tlsld_got
.refcount
> 0)
3023 htab
->tlsld_got
.offset
= htab
->elf
.sgot
->size
;
3024 htab
->elf
.sgot
->size
+= 8;
3025 if (bfd_link_pic (info
))
3026 htab
->elf
.srelgot
->size
+= sizeof (Elf32_External_Rela
);
3029 htab
->tlsld_got
.offset
= (bfd_vma
) -1;
3031 if (elf_hash_table (info
)->dynamic_sections_created
)
3033 /* Make space for the trailing nop in .plt. */
3034 if (htab
->elf
.splt
->size
> 0)
3035 htab
->elf
.splt
->size
+= 4;
3038 /* The check_relocs and adjust_dynamic_symbol entry points have
3039 determined the sizes of the various dynamic sections. Allocate
3041 for (s
= dynobj
->sections
; s
!= NULL
; s
= s
->next
)
3046 if ((s
->flags
& SEC_LINKER_CREATED
) == 0)
3049 /* It's OK to base decisions on the section name, because none
3050 of the dynobj section names depend upon the input files. */
3051 name
= bfd_section_name (s
);
3053 if (startswith (name
, ".rela"))
3057 /* If we don't need this section, strip it from the
3058 output file. This is to handle .rela.bss and
3059 .rela.plt. We must create it in
3060 create_dynamic_sections, because it must be created
3061 before the linker maps input sections to output
3062 sections. The linker does that before
3063 adjust_dynamic_symbol is called, and it is that
3064 function which decides whether anything needs to go
3065 into these sections. */
3070 /* We use the reloc_count field as a counter if we need
3071 to copy relocs into the output file. */
3075 else if (s
!= htab
->elf
.splt
3076 && s
!= htab
->elf
.sgot
3077 && s
!= htab
->elf
.sgotplt
3078 && s
!= htab
->elf
.sdynbss
3079 && s
!= htab
->elf
.sdynrelro
)
3081 /* It's not one of our sections, so don't allocate space. */
3087 s
->flags
|= SEC_EXCLUDE
;
3091 /* Allocate memory for the section contents. */
3092 /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
3093 Unused entries should be reclaimed before the section's contents
3094 are written out, but at the moment this does not happen. Thus in
3095 order to prevent writing out garbage, we initialise the section's
3096 contents to zero. */
3097 s
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, s
->size
);
3098 if (s
->contents
== NULL
&& s
->size
!= 0)
3102 /* ??? Force DF_BIND_NOW? */
3103 info
->flags
|= DF_BIND_NOW
;
3104 return _bfd_elf_add_dynamic_tags (output_bfd
, info
, true);
3107 /* Finish up dynamic symbol handling. We set the contents of various
3108 dynamic sections here. */
3111 microblaze_elf_finish_dynamic_symbol (bfd
*output_bfd
,
3112 struct bfd_link_info
*info
,
3113 struct elf_link_hash_entry
*h
,
3114 Elf_Internal_Sym
*sym
)
3116 struct elf32_mb_link_hash_table
*htab
;
3117 struct elf32_mb_link_hash_entry
*eh
= elf32_mb_hash_entry(h
);
3119 htab
= elf32_mb_hash_table (info
);
3123 if (h
->plt
.offset
!= (bfd_vma
) -1)
3128 Elf_Internal_Rela rela
;
3134 /* This symbol has an entry in the procedure linkage table. Set
3136 BFD_ASSERT (h
->dynindx
!= -1);
3138 splt
= htab
->elf
.splt
;
3139 srela
= htab
->elf
.srelplt
;
3140 sgotplt
= htab
->elf
.sgotplt
;
3141 BFD_ASSERT (splt
!= NULL
&& srela
!= NULL
&& sgotplt
!= NULL
);
3143 plt_index
= h
->plt
.offset
/ PLT_ENTRY_SIZE
- 1; /* first entry reserved. */
3144 got_offset
= (plt_index
+ 3) * 4; /* 3 reserved ??? */
3145 got_addr
= got_offset
;
3147 /* For non-PIC objects we need absolute address of the GOT entry. */
3148 if (!bfd_link_pic (info
))
3149 got_addr
+= sgotplt
->output_section
->vma
+ sgotplt
->output_offset
;
3151 /* Fill in the entry in the procedure linkage table. */
3152 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_0
+ ((got_addr
>> 16) & 0xffff),
3153 splt
->contents
+ h
->plt
.offset
);
3154 if (bfd_link_pic (info
))
3155 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_1
+ (got_addr
& 0xffff),
3156 splt
->contents
+ h
->plt
.offset
+ 4);
3158 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_1_NOPIC
+ (got_addr
& 0xffff),
3159 splt
->contents
+ h
->plt
.offset
+ 4);
3160 bfd_put_32 (output_bfd
, (bfd_vma
) PLT_ENTRY_WORD_2
,
3161 splt
->contents
+ h
->plt
.offset
+ 8);
3162 bfd_put_32 (output_bfd
, (bfd_vma
) PLT_ENTRY_WORD_3
,
3163 splt
->contents
+ h
->plt
.offset
+ 12);
3165 /* Any additions to the .got section??? */
3166 /* bfd_put_32 (output_bfd,
3167 splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
3168 sgotplt->contents + got_offset); */
3170 /* Fill in the entry in the .rela.plt section. */
3171 rela
.r_offset
= (sgotplt
->output_section
->vma
3172 + sgotplt
->output_offset
3174 rela
.r_info
= ELF32_R_INFO (h
->dynindx
, R_MICROBLAZE_JUMP_SLOT
);
3176 loc
= srela
->contents
;
3177 loc
+= plt_index
* sizeof (Elf32_External_Rela
);
3178 bfd_elf32_swap_reloca_out (output_bfd
, &rela
, loc
);
3180 if (!h
->def_regular
)
3182 /* Mark the symbol as undefined, rather than as defined in
3183 the .plt section. Zero the value. */
3184 sym
->st_shndx
= SHN_UNDEF
;
3189 /* h->got.refcount to be checked ? */
3190 if (h
->got
.offset
!= (bfd_vma
) -1 &&
3191 ! ((h
->got
.offset
& 1) ||
3192 IS_TLS_LD(eh
->tls_mask
) || IS_TLS_GD(eh
->tls_mask
)))
3198 /* This symbol has an entry in the global offset table. Set it
3201 sgot
= htab
->elf
.sgot
;
3202 srela
= htab
->elf
.srelgot
;
3203 BFD_ASSERT (sgot
!= NULL
&& srela
!= NULL
);
3205 offset
= (sgot
->output_section
->vma
+ sgot
->output_offset
3206 + (h
->got
.offset
&~ (bfd_vma
) 1));
3208 /* If this is a -Bsymbolic link, and the symbol is defined
3209 locally, we just want to emit a RELATIVE reloc. Likewise if
3210 the symbol was forced to be local because of a version file.
3211 The entry in the global offset table will already have been
3212 initialized in the relocate_section function. */
3213 if (bfd_link_pic (info
)
3214 && ((info
->symbolic
&& h
->def_regular
)
3215 || h
->dynindx
== -1))
3217 asection
*sec
= h
->root
.u
.def
.section
;
3220 value
= h
->root
.u
.def
.value
;
3221 if (sec
->output_section
!= NULL
)
3222 /* PR 21180: If the output section is NULL, then the symbol is no
3223 longer needed, and in theory the GOT entry is redundant. But
3224 it is too late to change our minds now... */
3225 value
+= sec
->output_section
->vma
+ sec
->output_offset
;
3227 microblaze_elf_output_dynamic_relocation (output_bfd
,
3228 srela
, srela
->reloc_count
++,
3230 R_MICROBLAZE_REL
, offset
,
3235 microblaze_elf_output_dynamic_relocation (output_bfd
,
3236 srela
, srela
->reloc_count
++,
3238 R_MICROBLAZE_GLOB_DAT
,
3242 bfd_put_32 (output_bfd
, (bfd_vma
) 0,
3243 sgot
->contents
+ (h
->got
.offset
&~ (bfd_vma
) 1));
3249 Elf_Internal_Rela rela
;
3252 /* This symbols needs a copy reloc. Set it up. */
3254 BFD_ASSERT (h
->dynindx
!= -1);
3256 rela
.r_offset
= (h
->root
.u
.def
.value
3257 + h
->root
.u
.def
.section
->output_section
->vma
3258 + h
->root
.u
.def
.section
->output_offset
);
3259 rela
.r_info
= ELF32_R_INFO (h
->dynindx
, R_MICROBLAZE_COPY
);
3261 if (h
->root
.u
.def
.section
== htab
->elf
.sdynrelro
)
3262 s
= htab
->elf
.sreldynrelro
;
3264 s
= htab
->elf
.srelbss
;
3265 loc
= s
->contents
+ s
->reloc_count
++ * sizeof (Elf32_External_Rela
);
3266 bfd_elf32_swap_reloca_out (output_bfd
, &rela
, loc
);
3269 /* Mark some specially defined symbols as absolute. */
3270 if (h
== htab
->elf
.hdynamic
3271 || h
== htab
->elf
.hgot
3272 || h
== htab
->elf
.hplt
)
3273 sym
->st_shndx
= SHN_ABS
;
3279 /* Finish up the dynamic sections. */
3282 microblaze_elf_finish_dynamic_sections (bfd
*output_bfd
,
3283 struct bfd_link_info
*info
)
3286 asection
*sdyn
, *sgot
;
3287 struct elf32_mb_link_hash_table
*htab
;
3289 htab
= elf32_mb_hash_table (info
);
3293 dynobj
= htab
->elf
.dynobj
;
3295 sdyn
= bfd_get_linker_section (dynobj
, ".dynamic");
3297 if (htab
->elf
.dynamic_sections_created
)
3300 Elf32_External_Dyn
*dyncon
, *dynconend
;
3302 dyncon
= (Elf32_External_Dyn
*) sdyn
->contents
;
3303 dynconend
= (Elf32_External_Dyn
*) (sdyn
->contents
+ sdyn
->size
);
3304 for (; dyncon
< dynconend
; dyncon
++)
3306 Elf_Internal_Dyn dyn
;
3310 bfd_elf32_swap_dyn_in (dynobj
, dyncon
, &dyn
);
3315 s
= htab
->elf
.sgotplt
;
3320 s
= htab
->elf
.srelplt
;
3325 s
= htab
->elf
.srelplt
;
3338 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
3340 dyn
.d_un
.d_val
= s
->size
;
3342 bfd_elf32_swap_dyn_out (output_bfd
, &dyn
, dyncon
);
3345 splt
= htab
->elf
.splt
;
3346 BFD_ASSERT (splt
!= NULL
&& sdyn
!= NULL
);
3348 /* Clear the first entry in the procedure linkage table,
3349 and put a nop in the last four bytes. */
3352 memset (splt
->contents
, 0, PLT_ENTRY_SIZE
);
3353 bfd_put_32 (output_bfd
, (bfd_vma
) 0x80000000 /* nop. */,
3354 splt
->contents
+ splt
->size
- 4);
3356 if (splt
->output_section
!= bfd_abs_section_ptr
)
3357 elf_section_data (splt
->output_section
)->this_hdr
.sh_entsize
= 4;
3361 /* Set the first entry in the global offset table to the address of
3362 the dynamic section. */
3363 sgot
= htab
->elf
.sgotplt
;
3364 if (sgot
&& sgot
->size
> 0)
3367 bfd_put_32 (output_bfd
, (bfd_vma
) 0, sgot
->contents
);
3369 bfd_put_32 (output_bfd
,
3370 sdyn
->output_section
->vma
+ sdyn
->output_offset
,
3372 elf_section_data (sgot
->output_section
)->this_hdr
.sh_entsize
= 4;
3375 if (htab
->elf
.sgot
&& htab
->elf
.sgot
->size
> 0)
3376 elf_section_data (htab
->elf
.sgot
->output_section
)->this_hdr
.sh_entsize
= 4;
3381 /* Hook called by the linker routine which adds symbols from an object
3382 file. We use it to put .comm items in .sbss, and not .bss. */
3385 microblaze_elf_add_symbol_hook (bfd
*abfd
,
3386 struct bfd_link_info
*info
,
3387 Elf_Internal_Sym
*sym
,
3388 const char **namep ATTRIBUTE_UNUSED
,
3389 flagword
*flagsp ATTRIBUTE_UNUSED
,
3393 if (sym
->st_shndx
== SHN_COMMON
3394 && !bfd_link_relocatable (info
)
3395 && sym
->st_size
<= elf_gp_size (abfd
))
3397 /* Common symbols less than or equal to -G nn bytes are automatically
3399 *secp
= bfd_make_section_old_way (abfd
, ".sbss");
3401 || !bfd_set_section_flags (*secp
, SEC_IS_COMMON
| SEC_SMALL_DATA
))
3404 *valp
= sym
->st_size
;
3410 #define TARGET_LITTLE_SYM microblaze_elf32_le_vec
3411 #define TARGET_LITTLE_NAME "elf32-microblazeel"
3413 #define TARGET_BIG_SYM microblaze_elf32_vec
3414 #define TARGET_BIG_NAME "elf32-microblaze"
3416 #define ELF_ARCH bfd_arch_microblaze
3417 #define ELF_TARGET_ID MICROBLAZE_ELF_DATA
3418 #define ELF_MACHINE_CODE EM_MICROBLAZE
3419 #define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
3420 #define ELF_MAXPAGESIZE 0x1000
3421 #define elf_info_to_howto microblaze_elf_info_to_howto
3422 #define elf_info_to_howto_rel NULL
3424 #define bfd_elf32_bfd_reloc_type_lookup microblaze_elf_reloc_type_lookup
3425 #define bfd_elf32_bfd_is_local_label_name microblaze_elf_is_local_label_name
3426 #define elf_backend_relocate_section microblaze_elf_relocate_section
3427 #define bfd_elf32_bfd_relax_section microblaze_elf_relax_section
3428 #define bfd_elf32_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
3429 #define bfd_elf32_bfd_reloc_name_lookup microblaze_elf_reloc_name_lookup
3431 #define elf_backend_gc_mark_hook microblaze_elf_gc_mark_hook
3432 #define elf_backend_check_relocs microblaze_elf_check_relocs
3433 #define elf_backend_copy_indirect_symbol microblaze_elf_copy_indirect_symbol
3434 #define bfd_elf32_bfd_link_hash_table_create microblaze_elf_link_hash_table_create
3435 #define elf_backend_can_gc_sections 1
3436 #define elf_backend_can_refcount 1
3437 #define elf_backend_want_got_plt 1
3438 #define elf_backend_plt_readonly 1
3439 #define elf_backend_got_header_size 12
3440 #define elf_backend_want_dynrelro 1
3441 #define elf_backend_rela_normal 1
3442 #define elf_backend_dtrel_excludes_plt 1
3444 #define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
3445 #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
3446 #define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
3447 #define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
3448 #define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections
3449 #define elf_backend_add_symbol_hook microblaze_elf_add_symbol_hook
3451 #include "elf32-target.h"