1 /* Xilinx MicroBlaze-specific support for 32-bit ELF
3 Copyright (C) 2009-2022 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
))
2091 if (ocontents
== NULL
)
2093 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2094 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2097 /* We always cache the section contents.
2098 Perhaps, if info->keep_memory is FALSE, we
2099 should free them, if we are permitted to. */
2101 if (o
->rawsize
== 0)
2102 o
->rawsize
= o
->size
;
2103 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2104 if (ocontents
== NULL
)
2106 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2110 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2113 offset
= calc_fixup (irelscan
->r_addend
, 0, sec
);
2114 irelscan
->r_addend
-= offset
;
2117 else if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_64_PCREL
)
2119 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2121 /* Look at the reloc only if the value has been resolved. */
2122 if (isym
->st_shndx
== shndx
2123 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
2126 bfd_vma target_address
;
2128 if (ocontents
== NULL
)
2130 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2131 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2134 /* We always cache the section contents.
2135 Perhaps, if info->keep_memory is FALSE, we
2136 should free them, if we are permitted to. */
2137 if (o
->rawsize
== 0)
2138 o
->rawsize
= o
->size
;
2139 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2140 if (ocontents
== NULL
)
2142 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2146 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2149 unsigned long instr_hi
= bfd_get_32 (abfd
, ocontents
2150 + irelscan
->r_offset
);
2151 unsigned long instr_lo
= bfd_get_32 (abfd
, ocontents
2152 + irelscan
->r_offset
2154 immediate
= (instr_hi
& 0x0000ffff) << 16;
2155 immediate
|= (instr_lo
& 0x0000ffff);
2156 target_address
= immediate
;
2157 offset
= calc_fixup (target_address
, 0, sec
);
2158 immediate
-= offset
;
2159 irelscan
->r_addend
-= offset
;
2160 microblaze_bfd_write_imm_value_64 (abfd
, ocontents
2161 + irelscan
->r_offset
, immediate
);
2167 /* Adjust the local symbols defined in this section. */
2168 isymend
= isymbuf
+ symtab_hdr
->sh_info
;
2169 for (isym
= isymbuf
; isym
< isymend
; isym
++)
2171 if (isym
->st_shndx
== shndx
)
2173 isym
->st_value
-= calc_fixup (isym
->st_value
, 0, sec
);
2175 isym
->st_size
-= calc_fixup (isym
->st_value
, isym
->st_size
, sec
);
2179 /* Now adjust the global symbols defined in this section. */
2180 isym
= isymbuf
+ symtab_hdr
->sh_info
;
2181 symcount
= (symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
)) - symtab_hdr
->sh_info
;
2182 for (sym_index
= 0; sym_index
< symcount
; sym_index
++)
2184 sym_hash
= elf_sym_hashes (abfd
)[sym_index
];
2185 if ((sym_hash
->root
.type
== bfd_link_hash_defined
2186 || sym_hash
->root
.type
== bfd_link_hash_defweak
)
2187 && sym_hash
->root
.u
.def
.section
== sec
)
2189 sym_hash
->root
.u
.def
.value
-= calc_fixup (sym_hash
->root
.u
.def
.value
,
2192 sym_hash
->size
-= calc_fixup (sym_hash
->root
.u
.def
.value
,
2193 sym_hash
->size
, sec
);
2197 /* Physically move the code and change the cooked size. */
2198 dest
= sec
->relax
[0].addr
;
2199 for (i
= 0; i
< sec
->relax_count
; i
++)
2202 src
= sec
->relax
[i
].addr
+ sec
->relax
[i
].size
;
2203 len
= sec
->relax
[i
+1].addr
- sec
->relax
[i
].addr
- sec
->relax
[i
].size
;
2205 memmove (contents
+ dest
, contents
+ src
, len
);
2206 sec
->size
-= sec
->relax
[i
].size
;
2210 elf_section_data (sec
)->relocs
= internal_relocs
;
2213 elf_section_data (sec
)->this_hdr
.contents
= contents
;
2214 free_contents
= NULL
;
2216 symtab_hdr
->contents
= (bfd_byte
*) isymbuf
;
2222 if (free_contents
!= NULL
)
2224 if (!link_info
->keep_memory
)
2225 free (free_contents
);
2227 /* Cache the section contents for elf_link_input_bfd. */
2228 elf_section_data (sec
)->this_hdr
.contents
= contents
;
2229 free_contents
= NULL
;
2232 if (sec
->relax_count
== 0)
2244 free (free_contents
);
2247 sec
->relax_count
= 0;
2251 /* Return the section that should be marked against GC for a given
2255 microblaze_elf_gc_mark_hook (asection
*sec
,
2256 struct bfd_link_info
* info
,
2257 Elf_Internal_Rela
* rel
,
2258 struct elf_link_hash_entry
* h
,
2259 Elf_Internal_Sym
* sym
)
2262 switch (ELF32_R_TYPE (rel
->r_info
))
2264 case R_MICROBLAZE_GNU_VTINHERIT
:
2265 case R_MICROBLAZE_GNU_VTENTRY
:
2269 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
2274 #define PLT_ENTRY_SIZE 16
2276 #define PLT_ENTRY_WORD_0 0xb0000000 /* "imm 0". */
2277 #define PLT_ENTRY_WORD_1 0xe9940000 /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT. */
2278 #define PLT_ENTRY_WORD_1_NOPIC 0xe9800000 /* "lwi r12,r0,0" - non-PIC object. */
2279 #define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
2280 #define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
2283 update_local_sym_info (bfd
*abfd
,
2284 Elf_Internal_Shdr
*symtab_hdr
,
2285 unsigned long r_symndx
,
2286 unsigned int tls_type
)
2288 bfd_signed_vma
*local_got_refcounts
= elf_local_got_refcounts (abfd
);
2289 unsigned char *local_got_tls_masks
;
2291 if (local_got_refcounts
== NULL
)
2293 bfd_size_type size
= symtab_hdr
->sh_info
;
2295 size
*= (sizeof (*local_got_refcounts
) + sizeof (*local_got_tls_masks
));
2296 local_got_refcounts
= bfd_zalloc (abfd
, size
);
2297 if (local_got_refcounts
== NULL
)
2299 elf_local_got_refcounts (abfd
) = local_got_refcounts
;
2302 local_got_tls_masks
=
2303 (unsigned char *) (local_got_refcounts
+ symtab_hdr
->sh_info
);
2304 local_got_tls_masks
[r_symndx
] |= tls_type
;
2305 local_got_refcounts
[r_symndx
] += 1;
2309 /* Look through the relocs for a section during the first phase. */
2312 microblaze_elf_check_relocs (bfd
* abfd
,
2313 struct bfd_link_info
* info
,
2315 const Elf_Internal_Rela
* relocs
)
2317 Elf_Internal_Shdr
* symtab_hdr
;
2318 struct elf_link_hash_entry
** sym_hashes
;
2319 const Elf_Internal_Rela
* rel
;
2320 const Elf_Internal_Rela
* rel_end
;
2321 struct elf32_mb_link_hash_table
*htab
;
2322 asection
*sreloc
= NULL
;
2324 if (bfd_link_relocatable (info
))
2327 htab
= elf32_mb_hash_table (info
);
2331 symtab_hdr
= & elf_tdata (abfd
)->symtab_hdr
;
2332 sym_hashes
= elf_sym_hashes (abfd
);
2334 rel_end
= relocs
+ sec
->reloc_count
;
2336 for (rel
= relocs
; rel
< rel_end
; rel
++)
2338 unsigned int r_type
;
2339 struct elf_link_hash_entry
* h
;
2340 unsigned long r_symndx
;
2341 unsigned char tls_type
= 0;
2343 r_symndx
= ELF32_R_SYM (rel
->r_info
);
2344 r_type
= ELF32_R_TYPE (rel
->r_info
);
2346 if (r_symndx
< symtab_hdr
->sh_info
)
2350 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
2351 while (h
->root
.type
== bfd_link_hash_indirect
2352 || h
->root
.type
== bfd_link_hash_warning
)
2353 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
2358 /* This relocation describes the C++ object vtable hierarchy.
2359 Reconstruct it for later use during GC. */
2360 case R_MICROBLAZE_GNU_VTINHERIT
:
2361 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
2365 /* This relocation describes which C++ vtable entries are actually
2366 used. Record for later use during GC. */
2367 case R_MICROBLAZE_GNU_VTENTRY
:
2368 if (!bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
2372 /* This relocation requires .plt entry. */
2373 case R_MICROBLAZE_PLT_64
:
2377 h
->plt
.refcount
+= 1;
2381 /* This relocation requires .got entry. */
2382 case R_MICROBLAZE_TLSGD
:
2383 tls_type
|= (TLS_TLS
| TLS_GD
);
2385 case R_MICROBLAZE_TLSLD
:
2386 tls_type
|= (TLS_TLS
| TLS_LD
);
2389 sec
->has_tls_reloc
= 1;
2391 case R_MICROBLAZE_GOT_64
:
2392 if (htab
->elf
.sgot
== NULL
)
2394 if (htab
->elf
.dynobj
== NULL
)
2395 htab
->elf
.dynobj
= abfd
;
2396 if (!_bfd_elf_create_got_section (htab
->elf
.dynobj
, info
))
2401 h
->got
.refcount
+= 1;
2402 elf32_mb_hash_entry (h
)->tls_mask
|= tls_type
;
2406 if (! update_local_sym_info(abfd
, symtab_hdr
, r_symndx
, tls_type
) )
2411 case R_MICROBLAZE_GOTOFF_64
:
2412 case R_MICROBLAZE_GOTOFF_32
:
2413 if (htab
->elf
.sgot
== NULL
)
2415 if (htab
->elf
.dynobj
== NULL
)
2416 htab
->elf
.dynobj
= abfd
;
2417 if (!_bfd_elf_create_got_section (htab
->elf
.dynobj
, info
))
2422 case R_MICROBLAZE_64
:
2423 case R_MICROBLAZE_64_PCREL
:
2424 case R_MICROBLAZE_32
:
2426 if (h
!= NULL
&& !bfd_link_pic (info
))
2428 /* we may need a copy reloc. */
2431 /* we may also need a .plt entry. */
2432 h
->plt
.refcount
+= 1;
2433 if (ELF32_R_TYPE (rel
->r_info
) != R_MICROBLAZE_64_PCREL
)
2434 h
->pointer_equality_needed
= 1;
2438 /* If we are creating a shared library, and this is a reloc
2439 against a global symbol, or a non PC relative reloc
2440 against a local symbol, then we need to copy the reloc
2441 into the shared library. However, if we are linking with
2442 -Bsymbolic, we do not need to copy a reloc against a
2443 global symbol which is defined in an object we are
2444 including in the link (i.e., DEF_REGULAR is set). At
2445 this point we have not seen all the input files, so it is
2446 possible that DEF_REGULAR is not set now but will be set
2447 later (it is never cleared). In case of a weak definition,
2448 DEF_REGULAR may be cleared later by a strong definition in
2449 a shared library. We account for that possibility below by
2450 storing information in the relocs_copied field of the hash
2451 table entry. A similar situation occurs when creating
2452 shared libraries and symbol visibility changes render the
2455 If on the other hand, we are creating an executable, we
2456 may need to keep relocations for symbols satisfied by a
2457 dynamic library if we manage to avoid copy relocs for the
2460 if ((bfd_link_pic (info
)
2461 && (sec
->flags
& SEC_ALLOC
) != 0
2462 && (r_type
!= R_MICROBLAZE_64_PCREL
2464 && (! info
->symbolic
2465 || h
->root
.type
== bfd_link_hash_defweak
2466 || !h
->def_regular
))))
2467 || (!bfd_link_pic (info
)
2468 && (sec
->flags
& SEC_ALLOC
) != 0
2470 && (h
->root
.type
== bfd_link_hash_defweak
2471 || !h
->def_regular
)))
2473 struct elf_dyn_relocs
*p
;
2474 struct elf_dyn_relocs
**head
;
2476 /* When creating a shared object, we must copy these
2477 relocs into the output file. We create a reloc
2478 section in dynobj and make room for the reloc. */
2484 if (htab
->elf
.dynobj
== NULL
)
2485 htab
->elf
.dynobj
= abfd
;
2486 dynobj
= htab
->elf
.dynobj
;
2488 sreloc
= _bfd_elf_make_dynamic_reloc_section (sec
, dynobj
,
2494 /* If this is a global symbol, we count the number of
2495 relocations we need for this symbol. */
2497 head
= &h
->dyn_relocs
;
2500 /* Track dynamic relocs needed for local syms too.
2501 We really need local syms available to do this
2505 Elf_Internal_Sym
*isym
;
2508 isym
= bfd_sym_from_r_symndx (&htab
->elf
.sym_cache
,
2513 s
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
2517 vpp
= &elf_section_data (s
)->local_dynrel
;
2518 head
= (struct elf_dyn_relocs
**) vpp
;
2522 if (p
== NULL
|| p
->sec
!= sec
)
2524 size_t amt
= sizeof *p
;
2525 p
= ((struct elf_dyn_relocs
*)
2526 bfd_alloc (htab
->elf
.dynobj
, amt
));
2537 if (r_type
== R_MICROBLAZE_64_PCREL
)
2548 /* Copy the extra info we tack onto an elf_link_hash_entry. */
2551 microblaze_elf_copy_indirect_symbol (struct bfd_link_info
*info
,
2552 struct elf_link_hash_entry
*dir
,
2553 struct elf_link_hash_entry
*ind
)
2555 struct elf32_mb_link_hash_entry
*edir
, *eind
;
2557 edir
= (struct elf32_mb_link_hash_entry
*) dir
;
2558 eind
= (struct elf32_mb_link_hash_entry
*) ind
;
2560 edir
->tls_mask
|= eind
->tls_mask
;
2562 _bfd_elf_link_hash_copy_indirect (info
, dir
, ind
);
2566 microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info
*info
,
2567 struct elf_link_hash_entry
*h
)
2569 struct elf32_mb_link_hash_table
*htab
;
2571 unsigned int power_of_two
;
2573 htab
= elf32_mb_hash_table (info
);
2577 /* If this is a function, put it in the procedure linkage table. We
2578 will fill in the contents of the procedure linkage table later,
2579 when we know the address of the .got section. */
2580 if (h
->type
== STT_FUNC
2583 if (h
->plt
.refcount
<= 0
2584 || SYMBOL_CALLS_LOCAL (info
, h
)
2585 || (ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
2586 && h
->root
.type
== bfd_link_hash_undefweak
))
2588 /* This case can occur if we saw a PLT reloc in an input
2589 file, but the symbol was never referred to by a dynamic
2590 object, or if all references were garbage collected. In
2591 such a case, we don't actually need to build a procedure
2592 linkage table, and we can just do a PC32 reloc instead. */
2593 h
->plt
.offset
= (bfd_vma
) -1;
2600 /* It's possible that we incorrectly decided a .plt reloc was
2601 needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
2602 check_relocs. We can't decide accurately between function and
2603 non-function syms in check-relocs; Objects loaded later in
2604 the link may change h->type. So fix it now. */
2605 h
->plt
.offset
= (bfd_vma
) -1;
2607 /* If this is a weak symbol, and there is a real definition, the
2608 processor independent code will have arranged for us to see the
2609 real definition first, and we can just use the same value. */
2610 if (h
->is_weakalias
)
2612 struct elf_link_hash_entry
*def
= weakdef (h
);
2613 BFD_ASSERT (def
->root
.type
== bfd_link_hash_defined
);
2614 h
->root
.u
.def
.section
= def
->root
.u
.def
.section
;
2615 h
->root
.u
.def
.value
= def
->root
.u
.def
.value
;
2619 /* This is a reference to a symbol defined by a dynamic object which
2620 is not a function. */
2622 /* If we are creating a shared library, we must presume that the
2623 only references to the symbol are via the global offset table.
2624 For such cases we need not do anything here; the relocations will
2625 be handled correctly by relocate_section. */
2626 if (bfd_link_pic (info
))
2629 /* If there are no references to this symbol that do not use the
2630 GOT, we don't need to generate a copy reloc. */
2631 if (!h
->non_got_ref
)
2634 /* If -z nocopyreloc was given, we won't generate them either. */
2635 if (info
->nocopyreloc
)
2641 /* If we don't find any dynamic relocs in read-only sections, then
2642 we'll be keeping the dynamic relocs and avoiding the copy reloc. */
2643 if (!_bfd_elf_readonly_dynrelocs (h
))
2649 /* We must allocate the symbol in our .dynbss section, which will
2650 become part of the .bss section of the executable. There will be
2651 an entry for this symbol in the .dynsym section. The dynamic
2652 object will contain position independent code, so all references
2653 from the dynamic object to this symbol will go through the global
2654 offset table. The dynamic linker will use the .dynsym entry to
2655 determine the address it must put in the global offset table, so
2656 both the dynamic object and the regular object will refer to the
2657 same memory location for the variable. */
2659 /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
2660 to copy the initial value out of the dynamic object and into the
2661 runtime process image. */
2662 if ((h
->root
.u
.def
.section
->flags
& SEC_READONLY
) != 0)
2664 s
= htab
->elf
.sdynrelro
;
2665 srel
= htab
->elf
.sreldynrelro
;
2669 s
= htab
->elf
.sdynbss
;
2670 srel
= htab
->elf
.srelbss
;
2672 if ((h
->root
.u
.def
.section
->flags
& SEC_ALLOC
) != 0)
2674 srel
->size
+= sizeof (Elf32_External_Rela
);
2678 /* We need to figure out the alignment required for this symbol. I
2679 have no idea how ELF linkers handle this. */
2680 power_of_two
= bfd_log2 (h
->size
);
2681 if (power_of_two
> 3)
2684 /* Apply the required alignment. */
2685 s
->size
= BFD_ALIGN (s
->size
, (bfd_size_type
) (1 << power_of_two
));
2686 if (power_of_two
> s
->alignment_power
)
2688 if (!bfd_set_section_alignment (s
, power_of_two
))
2692 /* Define the symbol as being at this point in the section. */
2693 h
->root
.u
.def
.section
= s
;
2694 h
->root
.u
.def
.value
= s
->size
;
2696 /* Increment the section size to make room for the symbol. */
2701 /* Allocate space in .plt, .got and associated reloc sections for
2705 allocate_dynrelocs (struct elf_link_hash_entry
*h
, void * dat
)
2707 struct bfd_link_info
*info
;
2708 struct elf32_mb_link_hash_table
*htab
;
2709 struct elf32_mb_link_hash_entry
*eh
;
2710 struct elf_dyn_relocs
*p
;
2712 if (h
->root
.type
== bfd_link_hash_indirect
)
2715 info
= (struct bfd_link_info
*) dat
;
2716 htab
= elf32_mb_hash_table (info
);
2720 if (htab
->elf
.dynamic_sections_created
2721 && h
->plt
.refcount
> 0)
2723 /* Make sure this symbol is output as a dynamic symbol.
2724 Undefined weak syms won't yet be marked as dynamic. */
2725 if (h
->dynindx
== -1
2726 && !h
->forced_local
)
2728 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2732 if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info
), h
))
2734 asection
*s
= htab
->elf
.splt
;
2736 /* The first entry in .plt is reserved. */
2738 s
->size
= PLT_ENTRY_SIZE
;
2740 h
->plt
.offset
= s
->size
;
2742 /* If this symbol is not defined in a regular file, and we are
2743 not generating a shared library, then set the symbol to this
2744 location in the .plt. This is required to make function
2745 pointers compare as equal between the normal executable and
2746 the shared library. */
2747 if (! bfd_link_pic (info
)
2750 h
->root
.u
.def
.section
= s
;
2751 h
->root
.u
.def
.value
= h
->plt
.offset
;
2754 /* Make room for this entry. */
2755 s
->size
+= PLT_ENTRY_SIZE
;
2757 /* We also need to make an entry in the .got.plt section, which
2758 will be placed in the .got section by the linker script. */
2759 htab
->elf
.sgotplt
->size
+= 4;
2761 /* We also need to make an entry in the .rel.plt section. */
2762 htab
->elf
.srelplt
->size
+= sizeof (Elf32_External_Rela
);
2766 h
->plt
.offset
= (bfd_vma
) -1;
2772 h
->plt
.offset
= (bfd_vma
) -1;
2776 eh
= (struct elf32_mb_link_hash_entry
*) h
;
2777 if (h
->got
.refcount
> 0)
2782 /* Make sure this symbol is output as a dynamic symbol.
2783 Undefined weak syms won't yet be marked as dynamic. */
2784 if (h
->dynindx
== -1
2785 && !h
->forced_local
)
2787 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2792 if ((eh
->tls_mask
& TLS_TLS
) != 0)
2794 /* Handle TLS Symbol */
2795 if ((eh
->tls_mask
& TLS_LD
) != 0)
2797 if (!eh
->elf
.def_dynamic
)
2798 /* We'll just use htab->tlsld_got.offset. This should
2799 always be the case. It's a little odd if we have
2800 a local dynamic reloc against a non-local symbol. */
2801 htab
->tlsld_got
.refcount
+= 1;
2805 if ((eh
->tls_mask
& TLS_GD
) != 0)
2810 /* Regular (non-TLS) symbol */
2815 h
->got
.offset
= (bfd_vma
) -1;
2820 h
->got
.offset
= s
->size
;
2822 htab
->elf
.srelgot
->size
+= need
* (sizeof (Elf32_External_Rela
) / 4);
2826 h
->got
.offset
= (bfd_vma
) -1;
2828 if (h
->dyn_relocs
== NULL
)
2831 /* In the shared -Bsymbolic case, discard space allocated for
2832 dynamic pc-relative relocs against symbols which turn out to be
2833 defined in regular objects. For the normal shared case, discard
2834 space for pc-relative relocs that have become local due to symbol
2835 visibility changes. */
2837 if (bfd_link_pic (info
))
2843 struct elf_dyn_relocs
**pp
;
2845 for (pp
= &h
->dyn_relocs
; (p
= *pp
) != NULL
; )
2847 p
->count
-= p
->pc_count
;
2855 else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
2856 h
->dyn_relocs
= NULL
;
2860 /* For the non-shared case, discard space for relocs against
2861 symbols which turn out to need copy relocs or are not
2867 || (htab
->elf
.dynamic_sections_created
2868 && (h
->root
.type
== bfd_link_hash_undefweak
2869 || h
->root
.type
== bfd_link_hash_undefined
))))
2871 /* Make sure this symbol is output as a dynamic symbol.
2872 Undefined weak syms won't yet be marked as dynamic. */
2873 if (h
->dynindx
== -1
2874 && !h
->forced_local
)
2876 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2880 /* If that succeeded, we know we'll be keeping all the
2882 if (h
->dynindx
!= -1)
2886 h
->dyn_relocs
= NULL
;
2891 /* Finally, allocate space. */
2892 for (p
= h
->dyn_relocs
; p
!= NULL
; p
= p
->next
)
2894 asection
*sreloc
= elf_section_data (p
->sec
)->sreloc
;
2895 sreloc
->size
+= p
->count
* sizeof (Elf32_External_Rela
);
2901 /* Set the sizes of the dynamic sections. */
2904 microblaze_elf_size_dynamic_sections (bfd
*output_bfd ATTRIBUTE_UNUSED
,
2905 struct bfd_link_info
*info
)
2907 struct elf32_mb_link_hash_table
*htab
;
2912 htab
= elf32_mb_hash_table (info
);
2916 dynobj
= htab
->elf
.dynobj
;
2917 BFD_ASSERT (dynobj
!= NULL
);
2919 /* Set up .got offsets for local syms, and space for local dynamic
2921 for (ibfd
= info
->input_bfds
; ibfd
!= NULL
; ibfd
= ibfd
->link
.next
)
2923 bfd_signed_vma
*local_got
;
2924 bfd_signed_vma
*end_local_got
;
2925 bfd_size_type locsymcount
;
2926 Elf_Internal_Shdr
*symtab_hdr
;
2927 unsigned char *lgot_masks
;
2930 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
)
2933 for (s
= ibfd
->sections
; s
!= NULL
; s
= s
->next
)
2935 struct elf_dyn_relocs
*p
;
2937 for (p
= ((struct elf_dyn_relocs
*)
2938 elf_section_data (s
)->local_dynrel
);
2942 if (!bfd_is_abs_section (p
->sec
)
2943 && bfd_is_abs_section (p
->sec
->output_section
))
2945 /* Input section has been discarded, either because
2946 it is a copy of a linkonce section or due to
2947 linker script /DISCARD/, so we'll be discarding
2950 else if (p
->count
!= 0)
2952 srel
= elf_section_data (p
->sec
)->sreloc
;
2953 srel
->size
+= p
->count
* sizeof (Elf32_External_Rela
);
2954 if ((p
->sec
->output_section
->flags
& SEC_READONLY
) != 0)
2955 info
->flags
|= DF_TEXTREL
;
2960 local_got
= elf_local_got_refcounts (ibfd
);
2964 symtab_hdr
= &elf_tdata (ibfd
)->symtab_hdr
;
2965 locsymcount
= symtab_hdr
->sh_info
;
2966 end_local_got
= local_got
+ locsymcount
;
2967 lgot_masks
= (unsigned char *) end_local_got
;
2969 srel
= htab
->elf
.srelgot
;
2971 for (; local_got
< end_local_got
; ++local_got
, ++lgot_masks
)
2975 unsigned int need
= 0;
2976 if ((*lgot_masks
& TLS_TLS
) != 0)
2978 if ((*lgot_masks
& TLS_GD
) != 0)
2980 if ((*lgot_masks
& TLS_LD
) != 0)
2981 htab
->tlsld_got
.refcount
+= 1;
2988 *local_got
= (bfd_vma
) -1;
2992 *local_got
= s
->size
;
2994 if (bfd_link_pic (info
))
2995 srel
->size
+= need
* (sizeof (Elf32_External_Rela
) / 4);
2999 *local_got
= (bfd_vma
) -1;
3003 /* Allocate global sym .plt and .got entries, and space for global
3004 sym dynamic relocs. */
3005 elf_link_hash_traverse (elf_hash_table (info
), allocate_dynrelocs
, info
);
3007 if (htab
->tlsld_got
.refcount
> 0)
3009 htab
->tlsld_got
.offset
= htab
->elf
.sgot
->size
;
3010 htab
->elf
.sgot
->size
+= 8;
3011 if (bfd_link_pic (info
))
3012 htab
->elf
.srelgot
->size
+= sizeof (Elf32_External_Rela
);
3015 htab
->tlsld_got
.offset
= (bfd_vma
) -1;
3017 if (elf_hash_table (info
)->dynamic_sections_created
)
3019 /* Make space for the trailing nop in .plt. */
3020 if (htab
->elf
.splt
->size
> 0)
3021 htab
->elf
.splt
->size
+= 4;
3024 /* The check_relocs and adjust_dynamic_symbol entry points have
3025 determined the sizes of the various dynamic sections. Allocate
3027 for (s
= dynobj
->sections
; s
!= NULL
; s
= s
->next
)
3032 if ((s
->flags
& SEC_LINKER_CREATED
) == 0)
3035 /* It's OK to base decisions on the section name, because none
3036 of the dynobj section names depend upon the input files. */
3037 name
= bfd_section_name (s
);
3039 if (startswith (name
, ".rela"))
3043 /* If we don't need this section, strip it from the
3044 output file. This is to handle .rela.bss and
3045 .rela.plt. We must create it in
3046 create_dynamic_sections, because it must be created
3047 before the linker maps input sections to output
3048 sections. The linker does that before
3049 adjust_dynamic_symbol is called, and it is that
3050 function which decides whether anything needs to go
3051 into these sections. */
3056 /* We use the reloc_count field as a counter if we need
3057 to copy relocs into the output file. */
3061 else if (s
!= htab
->elf
.splt
3062 && s
!= htab
->elf
.sgot
3063 && s
!= htab
->elf
.sgotplt
3064 && s
!= htab
->elf
.sdynbss
3065 && s
!= htab
->elf
.sdynrelro
)
3067 /* It's not one of our sections, so don't allocate space. */
3073 s
->flags
|= SEC_EXCLUDE
;
3077 /* Allocate memory for the section contents. */
3078 /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
3079 Unused entries should be reclaimed before the section's contents
3080 are written out, but at the moment this does not happen. Thus in
3081 order to prevent writing out garbage, we initialise the section's
3082 contents to zero. */
3083 s
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, s
->size
);
3084 if (s
->contents
== NULL
&& s
->size
!= 0)
3088 /* ??? Force DF_BIND_NOW? */
3089 info
->flags
|= DF_BIND_NOW
;
3090 return _bfd_elf_add_dynamic_tags (output_bfd
, info
, true);
3093 /* Finish up dynamic symbol handling. We set the contents of various
3094 dynamic sections here. */
3097 microblaze_elf_finish_dynamic_symbol (bfd
*output_bfd
,
3098 struct bfd_link_info
*info
,
3099 struct elf_link_hash_entry
*h
,
3100 Elf_Internal_Sym
*sym
)
3102 struct elf32_mb_link_hash_table
*htab
;
3103 struct elf32_mb_link_hash_entry
*eh
= elf32_mb_hash_entry(h
);
3105 htab
= elf32_mb_hash_table (info
);
3109 if (h
->plt
.offset
!= (bfd_vma
) -1)
3114 Elf_Internal_Rela rela
;
3120 /* This symbol has an entry in the procedure linkage table. Set
3122 BFD_ASSERT (h
->dynindx
!= -1);
3124 splt
= htab
->elf
.splt
;
3125 srela
= htab
->elf
.srelplt
;
3126 sgotplt
= htab
->elf
.sgotplt
;
3127 BFD_ASSERT (splt
!= NULL
&& srela
!= NULL
&& sgotplt
!= NULL
);
3129 plt_index
= h
->plt
.offset
/ PLT_ENTRY_SIZE
- 1; /* first entry reserved. */
3130 got_offset
= (plt_index
+ 3) * 4; /* 3 reserved ??? */
3131 got_addr
= got_offset
;
3133 /* For non-PIC objects we need absolute address of the GOT entry. */
3134 if (!bfd_link_pic (info
))
3135 got_addr
+= sgotplt
->output_section
->vma
+ sgotplt
->output_offset
;
3137 /* Fill in the entry in the procedure linkage table. */
3138 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_0
+ ((got_addr
>> 16) & 0xffff),
3139 splt
->contents
+ h
->plt
.offset
);
3140 if (bfd_link_pic (info
))
3141 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_1
+ (got_addr
& 0xffff),
3142 splt
->contents
+ h
->plt
.offset
+ 4);
3144 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_1_NOPIC
+ (got_addr
& 0xffff),
3145 splt
->contents
+ h
->plt
.offset
+ 4);
3146 bfd_put_32 (output_bfd
, (bfd_vma
) PLT_ENTRY_WORD_2
,
3147 splt
->contents
+ h
->plt
.offset
+ 8);
3148 bfd_put_32 (output_bfd
, (bfd_vma
) PLT_ENTRY_WORD_3
,
3149 splt
->contents
+ h
->plt
.offset
+ 12);
3151 /* Any additions to the .got section??? */
3152 /* bfd_put_32 (output_bfd,
3153 splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
3154 sgotplt->contents + got_offset); */
3156 /* Fill in the entry in the .rela.plt section. */
3157 rela
.r_offset
= (sgotplt
->output_section
->vma
3158 + sgotplt
->output_offset
3160 rela
.r_info
= ELF32_R_INFO (h
->dynindx
, R_MICROBLAZE_JUMP_SLOT
);
3162 loc
= srela
->contents
;
3163 loc
+= plt_index
* sizeof (Elf32_External_Rela
);
3164 bfd_elf32_swap_reloca_out (output_bfd
, &rela
, loc
);
3166 if (!h
->def_regular
)
3168 /* Mark the symbol as undefined, rather than as defined in
3169 the .plt section. Zero the value. */
3170 sym
->st_shndx
= SHN_UNDEF
;
3175 /* h->got.refcount to be checked ? */
3176 if (h
->got
.offset
!= (bfd_vma
) -1 &&
3177 ! ((h
->got
.offset
& 1) ||
3178 IS_TLS_LD(eh
->tls_mask
) || IS_TLS_GD(eh
->tls_mask
)))
3184 /* This symbol has an entry in the global offset table. Set it
3187 sgot
= htab
->elf
.sgot
;
3188 srela
= htab
->elf
.srelgot
;
3189 BFD_ASSERT (sgot
!= NULL
&& srela
!= NULL
);
3191 offset
= (sgot
->output_section
->vma
+ sgot
->output_offset
3192 + (h
->got
.offset
&~ (bfd_vma
) 1));
3194 /* If this is a -Bsymbolic link, and the symbol is defined
3195 locally, we just want to emit a RELATIVE reloc. Likewise if
3196 the symbol was forced to be local because of a version file.
3197 The entry in the global offset table will already have been
3198 initialized in the relocate_section function. */
3199 if (bfd_link_pic (info
)
3200 && ((info
->symbolic
&& h
->def_regular
)
3201 || h
->dynindx
== -1))
3203 asection
*sec
= h
->root
.u
.def
.section
;
3206 value
= h
->root
.u
.def
.value
;
3207 if (sec
->output_section
!= NULL
)
3208 /* PR 21180: If the output section is NULL, then the symbol is no
3209 longer needed, and in theory the GOT entry is redundant. But
3210 it is too late to change our minds now... */
3211 value
+= sec
->output_section
->vma
+ sec
->output_offset
;
3213 microblaze_elf_output_dynamic_relocation (output_bfd
,
3214 srela
, srela
->reloc_count
++,
3216 R_MICROBLAZE_REL
, offset
,
3221 microblaze_elf_output_dynamic_relocation (output_bfd
,
3222 srela
, srela
->reloc_count
++,
3224 R_MICROBLAZE_GLOB_DAT
,
3228 bfd_put_32 (output_bfd
, (bfd_vma
) 0,
3229 sgot
->contents
+ (h
->got
.offset
&~ (bfd_vma
) 1));
3235 Elf_Internal_Rela rela
;
3238 /* This symbols needs a copy reloc. Set it up. */
3240 BFD_ASSERT (h
->dynindx
!= -1);
3242 rela
.r_offset
= (h
->root
.u
.def
.value
3243 + h
->root
.u
.def
.section
->output_section
->vma
3244 + h
->root
.u
.def
.section
->output_offset
);
3245 rela
.r_info
= ELF32_R_INFO (h
->dynindx
, R_MICROBLAZE_COPY
);
3247 if (h
->root
.u
.def
.section
== htab
->elf
.sdynrelro
)
3248 s
= htab
->elf
.sreldynrelro
;
3250 s
= htab
->elf
.srelbss
;
3251 loc
= s
->contents
+ s
->reloc_count
++ * sizeof (Elf32_External_Rela
);
3252 bfd_elf32_swap_reloca_out (output_bfd
, &rela
, loc
);
3255 /* Mark some specially defined symbols as absolute. */
3256 if (h
== htab
->elf
.hdynamic
3257 || h
== htab
->elf
.hgot
3258 || h
== htab
->elf
.hplt
)
3259 sym
->st_shndx
= SHN_ABS
;
3265 /* Finish up the dynamic sections. */
3268 microblaze_elf_finish_dynamic_sections (bfd
*output_bfd
,
3269 struct bfd_link_info
*info
)
3272 asection
*sdyn
, *sgot
;
3273 struct elf32_mb_link_hash_table
*htab
;
3275 htab
= elf32_mb_hash_table (info
);
3279 dynobj
= htab
->elf
.dynobj
;
3281 sdyn
= bfd_get_linker_section (dynobj
, ".dynamic");
3283 if (htab
->elf
.dynamic_sections_created
)
3286 Elf32_External_Dyn
*dyncon
, *dynconend
;
3288 dyncon
= (Elf32_External_Dyn
*) sdyn
->contents
;
3289 dynconend
= (Elf32_External_Dyn
*) (sdyn
->contents
+ sdyn
->size
);
3290 for (; dyncon
< dynconend
; dyncon
++)
3292 Elf_Internal_Dyn dyn
;
3296 bfd_elf32_swap_dyn_in (dynobj
, dyncon
, &dyn
);
3301 s
= htab
->elf
.sgotplt
;
3306 s
= htab
->elf
.srelplt
;
3311 s
= htab
->elf
.srelplt
;
3324 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
3326 dyn
.d_un
.d_val
= s
->size
;
3328 bfd_elf32_swap_dyn_out (output_bfd
, &dyn
, dyncon
);
3331 splt
= htab
->elf
.splt
;
3332 BFD_ASSERT (splt
!= NULL
&& sdyn
!= NULL
);
3334 /* Clear the first entry in the procedure linkage table,
3335 and put a nop in the last four bytes. */
3338 memset (splt
->contents
, 0, PLT_ENTRY_SIZE
);
3339 bfd_put_32 (output_bfd
, (bfd_vma
) 0x80000000 /* nop. */,
3340 splt
->contents
+ splt
->size
- 4);
3342 if (splt
->output_section
!= bfd_abs_section_ptr
)
3343 elf_section_data (splt
->output_section
)->this_hdr
.sh_entsize
= 4;
3347 /* Set the first entry in the global offset table to the address of
3348 the dynamic section. */
3349 sgot
= htab
->elf
.sgotplt
;
3350 if (sgot
&& sgot
->size
> 0)
3353 bfd_put_32 (output_bfd
, (bfd_vma
) 0, sgot
->contents
);
3355 bfd_put_32 (output_bfd
,
3356 sdyn
->output_section
->vma
+ sdyn
->output_offset
,
3358 elf_section_data (sgot
->output_section
)->this_hdr
.sh_entsize
= 4;
3361 if (htab
->elf
.sgot
&& htab
->elf
.sgot
->size
> 0)
3362 elf_section_data (htab
->elf
.sgot
->output_section
)->this_hdr
.sh_entsize
= 4;
3367 /* Hook called by the linker routine which adds symbols from an object
3368 file. We use it to put .comm items in .sbss, and not .bss. */
3371 microblaze_elf_add_symbol_hook (bfd
*abfd
,
3372 struct bfd_link_info
*info
,
3373 Elf_Internal_Sym
*sym
,
3374 const char **namep ATTRIBUTE_UNUSED
,
3375 flagword
*flagsp ATTRIBUTE_UNUSED
,
3379 if (sym
->st_shndx
== SHN_COMMON
3380 && !bfd_link_relocatable (info
)
3381 && sym
->st_size
<= elf_gp_size (abfd
))
3383 /* Common symbols less than or equal to -G nn bytes are automatically
3385 *secp
= bfd_make_section_old_way (abfd
, ".sbss");
3387 || !bfd_set_section_flags (*secp
, SEC_IS_COMMON
| SEC_SMALL_DATA
))
3390 *valp
= sym
->st_size
;
3396 #define TARGET_LITTLE_SYM microblaze_elf32_le_vec
3397 #define TARGET_LITTLE_NAME "elf32-microblazeel"
3399 #define TARGET_BIG_SYM microblaze_elf32_vec
3400 #define TARGET_BIG_NAME "elf32-microblaze"
3402 #define ELF_ARCH bfd_arch_microblaze
3403 #define ELF_TARGET_ID MICROBLAZE_ELF_DATA
3404 #define ELF_MACHINE_CODE EM_MICROBLAZE
3405 #define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
3406 #define ELF_MAXPAGESIZE 0x1000
3407 #define elf_info_to_howto microblaze_elf_info_to_howto
3408 #define elf_info_to_howto_rel NULL
3410 #define bfd_elf32_bfd_reloc_type_lookup microblaze_elf_reloc_type_lookup
3411 #define bfd_elf32_bfd_is_local_label_name microblaze_elf_is_local_label_name
3412 #define elf_backend_relocate_section microblaze_elf_relocate_section
3413 #define bfd_elf32_bfd_relax_section microblaze_elf_relax_section
3414 #define bfd_elf32_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
3415 #define bfd_elf32_bfd_reloc_name_lookup microblaze_elf_reloc_name_lookup
3417 #define elf_backend_gc_mark_hook microblaze_elf_gc_mark_hook
3418 #define elf_backend_check_relocs microblaze_elf_check_relocs
3419 #define elf_backend_copy_indirect_symbol microblaze_elf_copy_indirect_symbol
3420 #define bfd_elf32_bfd_link_hash_table_create microblaze_elf_link_hash_table_create
3421 #define elf_backend_can_gc_sections 1
3422 #define elf_backend_can_refcount 1
3423 #define elf_backend_want_got_plt 1
3424 #define elf_backend_plt_readonly 1
3425 #define elf_backend_got_header_size 12
3426 #define elf_backend_want_dynrelro 1
3427 #define elf_backend_rela_normal 1
3428 #define elf_backend_dtrel_excludes_plt 1
3430 #define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
3431 #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
3432 #define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
3433 #define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
3434 #define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections
3435 #define elf_backend_add_symbol_hook microblaze_elf_add_symbol_hook
3437 #include "elf32-target.h"