1 /* Xilinx MicroBlaze-specific support for 32-bit ELF
3 Copyright (C) 2009-2020 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. */
30 #include "elf/microblaze.h"
33 #define USE_RELA /* Only USE_REL is actually significant, but this is
34 here are a reminder... */
35 #define INST_WORD_SIZE 4
37 static int ro_small_data_pointer
= 0;
38 static int rw_small_data_pointer
= 0;
40 static reloc_howto_type
* microblaze_elf_howto_table
[(int) R_MICROBLAZE_max
];
42 static reloc_howto_type microblaze_elf_howto_raw
[] =
44 /* This reloc does nothing. */
45 HOWTO (R_MICROBLAZE_NONE
, /* Type. */
47 3, /* Size (0 = byte, 1 = short, 2 = long). */
49 FALSE
, /* PC_relative. */
51 complain_overflow_dont
, /* Complain on overflow. */
52 NULL
, /* Special Function. */
53 "R_MICROBLAZE_NONE", /* Name. */
54 FALSE
, /* Partial Inplace. */
57 FALSE
), /* PC relative offset? */
59 /* A standard 32 bit relocation. */
60 HOWTO (R_MICROBLAZE_32
, /* Type. */
62 2, /* Size (0 = byte, 1 = short, 2 = long). */
64 FALSE
, /* PC_relative. */
66 complain_overflow_bitfield
, /* Complain on overflow. */
67 bfd_elf_generic_reloc
,/* Special Function. */
68 "R_MICROBLAZE_32", /* Name. */
69 FALSE
, /* Partial Inplace. */
71 0xffffffff, /* Dest Mask. */
72 FALSE
), /* PC relative offset? */
74 /* A standard PCREL 32 bit relocation. */
75 HOWTO (R_MICROBLAZE_32_PCREL
,/* Type. */
77 2, /* Size (0 = byte, 1 = short, 2 = long). */
79 TRUE
, /* PC_relative. */
81 complain_overflow_bitfield
, /* Complain on overflow. */
82 bfd_elf_generic_reloc
,/* Special Function. */
83 "R_MICROBLAZE_32_PCREL", /* Name. */
84 TRUE
, /* Partial Inplace. */
86 0xffffffff, /* Dest Mask. */
87 TRUE
), /* PC relative offset? */
89 /* A 64 bit PCREL relocation. Table-entry not really used. */
90 HOWTO (R_MICROBLAZE_64_PCREL
,/* Type. */
92 2, /* Size (0 = byte, 1 = short, 2 = long). */
94 TRUE
, /* PC_relative. */
96 complain_overflow_dont
, /* Complain on overflow. */
97 bfd_elf_generic_reloc
,/* Special Function. */
98 "R_MICROBLAZE_64_PCREL", /* Name. */
99 FALSE
, /* Partial Inplace. */
100 0, /* Source Mask. */
101 0x0000ffff, /* Dest Mask. */
102 TRUE
), /* PC relative offset? */
104 /* The low half of a PCREL 32 bit relocation. */
105 HOWTO (R_MICROBLAZE_32_PCREL_LO
, /* Type. */
107 2, /* Size (0 = byte, 1 = short, 2 = long). */
109 TRUE
, /* PC_relative. */
111 complain_overflow_signed
, /* Complain on overflow. */
112 bfd_elf_generic_reloc
, /* Special Function. */
113 "R_MICROBLAZE_32_PCREL_LO", /* Name. */
114 FALSE
, /* Partial Inplace. */
115 0, /* Source Mask. */
116 0x0000ffff, /* Dest Mask. */
117 TRUE
), /* PC relative offset? */
119 /* A 64 bit relocation. Table entry not really used. */
120 HOWTO (R_MICROBLAZE_64
, /* Type. */
122 2, /* Size (0 = byte, 1 = short, 2 = long). */
124 FALSE
, /* PC_relative. */
126 complain_overflow_dont
, /* Complain on overflow. */
127 bfd_elf_generic_reloc
,/* Special Function. */
128 "R_MICROBLAZE_64", /* Name. */
129 FALSE
, /* Partial Inplace. */
130 0, /* Source Mask. */
131 0x0000ffff, /* Dest Mask. */
132 FALSE
), /* PC relative offset? */
134 /* The low half of a 32 bit relocation. */
135 HOWTO (R_MICROBLAZE_32_LO
, /* Type. */
137 2, /* Size (0 = byte, 1 = short, 2 = long). */
139 FALSE
, /* PC_relative. */
141 complain_overflow_signed
, /* Complain on overflow. */
142 bfd_elf_generic_reloc
,/* Special Function. */
143 "R_MICROBLAZE_32_LO", /* Name. */
144 FALSE
, /* Partial Inplace. */
145 0, /* Source Mask. */
146 0x0000ffff, /* Dest Mask. */
147 FALSE
), /* PC relative offset? */
149 /* Read-only small data section relocation. */
150 HOWTO (R_MICROBLAZE_SRO32
, /* Type. */
152 2, /* Size (0 = byte, 1 = short, 2 = long). */
154 FALSE
, /* PC_relative. */
156 complain_overflow_bitfield
, /* Complain on overflow. */
157 bfd_elf_generic_reloc
,/* Special Function. */
158 "R_MICROBLAZE_SRO32", /* Name. */
159 FALSE
, /* Partial Inplace. */
160 0, /* Source Mask. */
161 0x0000ffff, /* Dest Mask. */
162 FALSE
), /* PC relative offset? */
164 /* Read-write small data area relocation. */
165 HOWTO (R_MICROBLAZE_SRW32
, /* Type. */
167 2, /* Size (0 = byte, 1 = short, 2 = long). */
169 FALSE
, /* PC_relative. */
171 complain_overflow_bitfield
, /* Complain on overflow. */
172 bfd_elf_generic_reloc
,/* Special Function. */
173 "R_MICROBLAZE_SRW32", /* Name. */
174 FALSE
, /* Partial Inplace. */
175 0, /* Source Mask. */
176 0x0000ffff, /* Dest Mask. */
177 FALSE
), /* PC relative offset? */
179 /* This reloc does nothing. Used for relaxation. */
180 HOWTO (R_MICROBLAZE_64_NONE
, /* Type. */
182 3, /* Size (0 = byte, 1 = short, 2 = long). */
184 TRUE
, /* PC_relative. */
186 complain_overflow_dont
, /* Complain on overflow. */
187 NULL
, /* Special Function. */
188 "R_MICROBLAZE_64_NONE",/* Name. */
189 FALSE
, /* Partial Inplace. */
190 0, /* Source Mask. */
192 FALSE
), /* PC relative offset? */
194 /* Symbol Op Symbol relocation. */
195 HOWTO (R_MICROBLAZE_32_SYM_OP_SYM
, /* Type. */
197 2, /* Size (0 = byte, 1 = short, 2 = long). */
199 FALSE
, /* PC_relative. */
201 complain_overflow_bitfield
, /* Complain on overflow. */
202 bfd_elf_generic_reloc
,/* Special Function. */
203 "R_MICROBLAZE_32_SYM_OP_SYM", /* Name. */
204 FALSE
, /* Partial Inplace. */
205 0, /* Source Mask. */
206 0xffffffff, /* Dest Mask. */
207 FALSE
), /* PC relative offset? */
209 /* GNU extension to record C++ vtable hierarchy. */
210 HOWTO (R_MICROBLAZE_GNU_VTINHERIT
, /* Type. */
212 2, /* Size (0 = byte, 1 = short, 2 = long). */
214 FALSE
, /* PC_relative. */
216 complain_overflow_dont
,/* Complain on overflow. */
217 NULL
, /* Special Function. */
218 "R_MICROBLAZE_GNU_VTINHERIT", /* Name. */
219 FALSE
, /* Partial Inplace. */
220 0, /* Source Mask. */
222 FALSE
), /* PC relative offset? */
224 /* GNU extension to record C++ vtable member usage. */
225 HOWTO (R_MICROBLAZE_GNU_VTENTRY
, /* Type. */
227 2, /* Size (0 = byte, 1 = short, 2 = long). */
229 FALSE
, /* PC_relative. */
231 complain_overflow_dont
,/* Complain on overflow. */
232 _bfd_elf_rel_vtable_reloc_fn
, /* Special Function. */
233 "R_MICROBLAZE_GNU_VTENTRY", /* Name. */
234 FALSE
, /* Partial Inplace. */
235 0, /* Source Mask. */
237 FALSE
), /* PC relative offset? */
239 /* A 64 bit GOTPC relocation. Table-entry not really used. */
240 HOWTO (R_MICROBLAZE_GOTPC_64
, /* Type. */
242 2, /* Size (0 = byte, 1 = short, 2 = long). */
244 TRUE
, /* PC_relative. */
246 complain_overflow_dont
, /* Complain on overflow. */
247 bfd_elf_generic_reloc
, /* Special Function. */
248 "R_MICROBLAZE_GOTPC_64", /* Name. */
249 FALSE
, /* Partial Inplace. */
250 0, /* Source Mask. */
251 0x0000ffff, /* Dest Mask. */
252 TRUE
), /* PC relative offset? */
254 /* A 64 bit TEXTPCREL relocation. Table-entry not really used. */
255 HOWTO (R_MICROBLAZE_TEXTPCREL_64
, /* Type. */
257 2, /* Size (0 = byte, 1 = short, 2 = long). */
259 TRUE
, /* PC_relative. */
261 complain_overflow_dont
, /* Complain on overflow. */
262 bfd_elf_generic_reloc
, /* Special Function. */
263 "R_MICROBLAZE_TEXTPCREL_64", /* Name. */
264 FALSE
, /* Partial Inplace. */
265 0, /* Source Mask. */
266 0x0000ffff, /* Dest Mask. */
267 TRUE
), /* PC relative offset? */
269 /* A 64 bit GOT relocation. Table-entry not really used. */
270 HOWTO (R_MICROBLAZE_GOT_64
, /* Type. */
272 2, /* Size (0 = byte, 1 = short, 2 = long). */
274 FALSE
, /* PC_relative. */
276 complain_overflow_dont
, /* Complain on overflow. */
277 bfd_elf_generic_reloc
,/* Special Function. */
278 "R_MICROBLAZE_GOT_64",/* Name. */
279 FALSE
, /* Partial Inplace. */
280 0, /* Source Mask. */
281 0x0000ffff, /* Dest Mask. */
282 FALSE
), /* PC relative offset? */
284 /* A 64 bit TEXTREL relocation. Table-entry not really used. */
285 HOWTO (R_MICROBLAZE_TEXTREL_64
, /* Type. */
287 2, /* Size (0 = byte, 1 = short, 2 = long). */
289 FALSE
, /* PC_relative. */
291 complain_overflow_dont
, /* Complain on overflow. */
292 bfd_elf_generic_reloc
,/* Special Function. */
293 "R_MICROBLAZE_TEXTREL_64",/* Name. */
294 FALSE
, /* Partial Inplace. */
295 0, /* Source Mask. */
296 0x0000ffff, /* Dest Mask. */
297 FALSE
), /* PC relative offset? */
299 /* A 64 bit PLT relocation. Table-entry not really used. */
300 HOWTO (R_MICROBLAZE_PLT_64
, /* Type. */
302 2, /* Size (0 = byte, 1 = short, 2 = long). */
304 TRUE
, /* PC_relative. */
306 complain_overflow_dont
, /* Complain on overflow. */
307 bfd_elf_generic_reloc
,/* Special Function. */
308 "R_MICROBLAZE_PLT_64",/* Name. */
309 FALSE
, /* Partial Inplace. */
310 0, /* Source Mask. */
311 0x0000ffff, /* Dest Mask. */
312 TRUE
), /* PC relative offset? */
314 /* Table-entry not really used. */
315 HOWTO (R_MICROBLAZE_REL
, /* Type. */
317 2, /* Size (0 = byte, 1 = short, 2 = long). */
319 TRUE
, /* PC_relative. */
321 complain_overflow_dont
, /* Complain on overflow. */
322 bfd_elf_generic_reloc
,/* Special Function. */
323 "R_MICROBLAZE_REL", /* Name. */
324 FALSE
, /* Partial Inplace. */
325 0, /* Source Mask. */
326 0x0000ffff, /* Dest Mask. */
327 TRUE
), /* PC relative offset? */
329 /* Table-entry not really used. */
330 HOWTO (R_MICROBLAZE_JUMP_SLOT
,/* Type. */
332 2, /* Size (0 = byte, 1 = short, 2 = long). */
334 TRUE
, /* PC_relative. */
336 complain_overflow_dont
, /* Complain on overflow. */
337 bfd_elf_generic_reloc
,/* Special Function. */
338 "R_MICROBLAZE_JUMP_SLOT", /* Name. */
339 FALSE
, /* Partial Inplace. */
340 0, /* Source Mask. */
341 0x0000ffff, /* Dest Mask. */
342 TRUE
), /* PC relative offset? */
344 /* Table-entry not really used. */
345 HOWTO (R_MICROBLAZE_GLOB_DAT
,/* Type. */
347 2, /* Size (0 = byte, 1 = short, 2 = long). */
349 TRUE
, /* PC_relative. */
351 complain_overflow_dont
, /* Complain on overflow. */
352 bfd_elf_generic_reloc
,/* Special Function. */
353 "R_MICROBLAZE_GLOB_DAT", /* Name. */
354 FALSE
, /* Partial Inplace. */
355 0, /* Source Mask. */
356 0x0000ffff, /* Dest Mask. */
357 TRUE
), /* PC relative offset? */
359 /* A 64 bit GOT relative relocation. Table-entry not really used. */
360 HOWTO (R_MICROBLAZE_GOTOFF_64
, /* Type. */
362 2, /* Size (0 = byte, 1 = short, 2 = long). */
364 FALSE
, /* PC_relative. */
366 complain_overflow_dont
, /* Complain on overflow. */
367 bfd_elf_generic_reloc
,/* Special Function. */
368 "R_MICROBLAZE_GOTOFF_64", /* Name. */
369 FALSE
, /* Partial Inplace. */
370 0, /* Source Mask. */
371 0x0000ffff, /* Dest Mask. */
372 FALSE
), /* PC relative offset? */
374 /* A 32 bit GOT relative relocation. Table-entry not really used. */
375 HOWTO (R_MICROBLAZE_GOTOFF_32
, /* Type. */
377 2, /* Size (0 = byte, 1 = short, 2 = long). */
379 FALSE
, /* PC_relative. */
381 complain_overflow_dont
, /* Complain on overflow. */
382 bfd_elf_generic_reloc
, /* Special Function. */
383 "R_MICROBLAZE_GOTOFF_32", /* Name. */
384 FALSE
, /* Partial Inplace. */
385 0, /* Source Mask. */
386 0x0000ffff, /* Dest Mask. */
387 FALSE
), /* PC relative offset? */
389 /* COPY relocation. Table-entry not really used. */
390 HOWTO (R_MICROBLAZE_COPY
, /* Type. */
392 2, /* Size (0 = byte, 1 = short, 2 = long). */
394 FALSE
, /* PC_relative. */
396 complain_overflow_dont
, /* Complain on overflow. */
397 bfd_elf_generic_reloc
,/* Special Function. */
398 "R_MICROBLAZE_COPY", /* Name. */
399 FALSE
, /* Partial Inplace. */
400 0, /* Source Mask. */
401 0x0000ffff, /* Dest Mask. */
402 FALSE
), /* PC relative offset? */
404 /* Marker relocs for TLS. */
405 HOWTO (R_MICROBLAZE_TLS
,
407 2, /* size (0 = byte, 1 = short, 2 = long) */
409 FALSE
, /* pc_relative */
411 complain_overflow_dont
, /* complain_on_overflow */
412 bfd_elf_generic_reloc
, /* special_function */
413 "R_MICROBLAZE_TLS", /* name */
414 FALSE
, /* partial_inplace */
416 0x0000ffff, /* dst_mask */
417 FALSE
), /* pcrel_offset */
419 HOWTO (R_MICROBLAZE_TLSGD
,
421 2, /* size (0 = byte, 1 = short, 2 = long) */
423 FALSE
, /* pc_relative */
425 complain_overflow_dont
, /* complain_on_overflow */
426 bfd_elf_generic_reloc
, /* special_function */
427 "R_MICROBLAZE_TLSGD", /* name */
428 FALSE
, /* partial_inplace */
430 0x0000ffff, /* dst_mask */
431 FALSE
), /* pcrel_offset */
433 HOWTO (R_MICROBLAZE_TLSLD
,
435 2, /* size (0 = byte, 1 = short, 2 = long) */
437 FALSE
, /* pc_relative */
439 complain_overflow_dont
, /* complain_on_overflow */
440 bfd_elf_generic_reloc
, /* special_function */
441 "R_MICROBLAZE_TLSLD", /* name */
442 FALSE
, /* partial_inplace */
444 0x0000ffff, /* dst_mask */
445 FALSE
), /* pcrel_offset */
447 /* Computes the load module index of the load module that contains the
448 definition of its TLS sym. */
449 HOWTO (R_MICROBLAZE_TLSDTPMOD32
,
451 2, /* size (0 = byte, 1 = short, 2 = long) */
453 FALSE
, /* pc_relative */
455 complain_overflow_dont
, /* complain_on_overflow */
456 bfd_elf_generic_reloc
, /* special_function */
457 "R_MICROBLAZE_TLSDTPMOD32", /* name */
458 FALSE
, /* partial_inplace */
460 0x0000ffff, /* dst_mask */
461 FALSE
), /* pcrel_offset */
463 /* Computes a dtv-relative displacement, the difference between the value
464 of sym+add and the base address of the thread-local storage block that
465 contains the definition of sym, minus 0x8000. Used for initializing GOT */
466 HOWTO (R_MICROBLAZE_TLSDTPREL32
,
468 2, /* size (0 = byte, 1 = short, 2 = long) */
470 FALSE
, /* pc_relative */
472 complain_overflow_dont
, /* complain_on_overflow */
473 bfd_elf_generic_reloc
, /* special_function */
474 "R_MICROBLAZE_TLSDTPREL32", /* name */
475 FALSE
, /* partial_inplace */
477 0x0000ffff, /* dst_mask */
478 FALSE
), /* pcrel_offset */
480 /* Computes a dtv-relative displacement, the difference between the value
481 of sym+add and the base address of the thread-local storage block that
482 contains the definition of sym, minus 0x8000. */
483 HOWTO (R_MICROBLAZE_TLSDTPREL64
,
485 2, /* size (0 = byte, 1 = short, 2 = long) */
487 FALSE
, /* pc_relative */
489 complain_overflow_dont
, /* complain_on_overflow */
490 bfd_elf_generic_reloc
, /* special_function */
491 "R_MICROBLAZE_TLSDTPREL64", /* name */
492 FALSE
, /* partial_inplace */
494 0x0000ffff, /* dst_mask */
495 FALSE
), /* pcrel_offset */
497 /* Computes a tp-relative displacement, the difference between the value of
498 sym+add and the value of the thread pointer (r13). */
499 HOWTO (R_MICROBLAZE_TLSGOTTPREL32
,
501 2, /* size (0 = byte, 1 = short, 2 = long) */
503 FALSE
, /* pc_relative */
505 complain_overflow_dont
, /* complain_on_overflow */
506 bfd_elf_generic_reloc
, /* special_function */
507 "R_MICROBLAZE_TLSGOTTPREL32", /* name */
508 FALSE
, /* partial_inplace */
510 0x0000ffff, /* dst_mask */
511 FALSE
), /* pcrel_offset */
513 /* Computes a tp-relative displacement, the difference between the value of
514 sym+add and the value of the thread pointer (r13). */
515 HOWTO (R_MICROBLAZE_TLSTPREL32
,
517 2, /* size (0 = byte, 1 = short, 2 = long) */
519 FALSE
, /* pc_relative */
521 complain_overflow_dont
, /* complain_on_overflow */
522 bfd_elf_generic_reloc
, /* special_function */
523 "R_MICROBLAZE_TLSTPREL32", /* name */
524 FALSE
, /* partial_inplace */
526 0x0000ffff, /* dst_mask */
527 FALSE
), /* pcrel_offset */
532 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
535 /* Initialize the microblaze_elf_howto_table, so that linear accesses can be done. */
538 microblaze_elf_howto_init (void)
542 for (i
= NUM_ELEM (microblaze_elf_howto_raw
); i
--;)
546 type
= microblaze_elf_howto_raw
[i
].type
;
548 BFD_ASSERT (type
< NUM_ELEM (microblaze_elf_howto_table
));
550 microblaze_elf_howto_table
[type
] = & microblaze_elf_howto_raw
[i
];
554 static reloc_howto_type
*
555 microblaze_elf_reloc_type_lookup (bfd
* abfd ATTRIBUTE_UNUSED
,
556 bfd_reloc_code_real_type code
)
558 enum elf_microblaze_reloc_type microblaze_reloc
= R_MICROBLAZE_NONE
;
563 microblaze_reloc
= R_MICROBLAZE_NONE
;
565 case BFD_RELOC_MICROBLAZE_64_NONE
:
566 microblaze_reloc
= R_MICROBLAZE_64_NONE
;
569 microblaze_reloc
= R_MICROBLAZE_32
;
571 /* RVA is treated the same as 32 */
573 microblaze_reloc
= R_MICROBLAZE_32
;
575 case BFD_RELOC_32_PCREL
:
576 microblaze_reloc
= R_MICROBLAZE_32_PCREL
;
578 case BFD_RELOC_64_PCREL
:
579 microblaze_reloc
= R_MICROBLAZE_64_PCREL
;
581 case BFD_RELOC_MICROBLAZE_32_LO_PCREL
:
582 microblaze_reloc
= R_MICROBLAZE_32_PCREL_LO
;
585 microblaze_reloc
= R_MICROBLAZE_64
;
587 case BFD_RELOC_MICROBLAZE_32_LO
:
588 microblaze_reloc
= R_MICROBLAZE_32_LO
;
590 case BFD_RELOC_MICROBLAZE_32_ROSDA
:
591 microblaze_reloc
= R_MICROBLAZE_SRO32
;
593 case BFD_RELOC_MICROBLAZE_32_RWSDA
:
594 microblaze_reloc
= R_MICROBLAZE_SRW32
;
596 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM
:
597 microblaze_reloc
= R_MICROBLAZE_32_SYM_OP_SYM
;
599 case BFD_RELOC_VTABLE_INHERIT
:
600 microblaze_reloc
= R_MICROBLAZE_GNU_VTINHERIT
;
602 case BFD_RELOC_VTABLE_ENTRY
:
603 microblaze_reloc
= R_MICROBLAZE_GNU_VTENTRY
;
605 case BFD_RELOC_MICROBLAZE_64_GOTPC
:
606 microblaze_reloc
= R_MICROBLAZE_GOTPC_64
;
608 case BFD_RELOC_MICROBLAZE_64_GOT
:
609 microblaze_reloc
= R_MICROBLAZE_GOT_64
;
611 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL
:
612 microblaze_reloc
= R_MICROBLAZE_TEXTPCREL_64
;
614 case BFD_RELOC_MICROBLAZE_64_TEXTREL
:
615 microblaze_reloc
= R_MICROBLAZE_TEXTREL_64
;
617 case BFD_RELOC_MICROBLAZE_64_PLT
:
618 microblaze_reloc
= R_MICROBLAZE_PLT_64
;
620 case BFD_RELOC_MICROBLAZE_64_GOTOFF
:
621 microblaze_reloc
= R_MICROBLAZE_GOTOFF_64
;
623 case BFD_RELOC_MICROBLAZE_32_GOTOFF
:
624 microblaze_reloc
= R_MICROBLAZE_GOTOFF_32
;
626 case BFD_RELOC_MICROBLAZE_64_TLSGD
:
627 microblaze_reloc
= R_MICROBLAZE_TLSGD
;
629 case BFD_RELOC_MICROBLAZE_64_TLSLD
:
630 microblaze_reloc
= R_MICROBLAZE_TLSLD
;
632 case BFD_RELOC_MICROBLAZE_32_TLSDTPREL
:
633 microblaze_reloc
= R_MICROBLAZE_TLSDTPREL32
;
635 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL
:
636 microblaze_reloc
= R_MICROBLAZE_TLSDTPREL64
;
638 case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD
:
639 microblaze_reloc
= R_MICROBLAZE_TLSDTPMOD32
;
641 case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL
:
642 microblaze_reloc
= R_MICROBLAZE_TLSGOTTPREL32
;
644 case BFD_RELOC_MICROBLAZE_64_TLSTPREL
:
645 microblaze_reloc
= R_MICROBLAZE_TLSTPREL32
;
647 case BFD_RELOC_MICROBLAZE_COPY
:
648 microblaze_reloc
= R_MICROBLAZE_COPY
;
651 return (reloc_howto_type
*) NULL
;
654 if (!microblaze_elf_howto_table
[R_MICROBLAZE_32
])
655 /* Initialize howto table if needed. */
656 microblaze_elf_howto_init ();
658 return microblaze_elf_howto_table
[(int) microblaze_reloc
];
661 static reloc_howto_type
*
662 microblaze_elf_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
667 for (i
= 0; i
< NUM_ELEM (microblaze_elf_howto_raw
); i
++)
668 if (microblaze_elf_howto_raw
[i
].name
!= NULL
669 && strcasecmp (microblaze_elf_howto_raw
[i
].name
, r_name
) == 0)
670 return µblaze_elf_howto_raw
[i
];
675 /* Set the howto pointer for a RCE ELF reloc. */
678 microblaze_elf_info_to_howto (bfd
* abfd
,
680 Elf_Internal_Rela
* dst
)
684 if (!microblaze_elf_howto_table
[R_MICROBLAZE_32
])
685 /* Initialize howto table if needed. */
686 microblaze_elf_howto_init ();
688 r_type
= ELF32_R_TYPE (dst
->r_info
);
689 if (r_type
>= R_MICROBLAZE_max
)
691 /* xgettext:c-format */
692 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
694 bfd_set_error (bfd_error_bad_value
);
698 cache_ptr
->howto
= microblaze_elf_howto_table
[r_type
];
702 /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'. */
705 microblaze_elf_is_local_label_name (bfd
*abfd
, const char *name
)
707 if (name
[0] == 'L' && name
[1] == '.')
710 if (name
[0] == '$' && name
[1] == 'L')
713 /* With gcc, the labels go back to starting with '.', so we accept
714 the generic ELF local label syntax as well. */
715 return _bfd_elf_is_local_label_name (abfd
, name
);
718 /* ELF linker hash entry. */
720 struct elf32_mb_link_hash_entry
722 struct elf_link_hash_entry elf
;
724 /* TLS Reference Types for the symbol; Updated by check_relocs */
725 #define TLS_GD 1 /* GD reloc. */
726 #define TLS_LD 2 /* LD reloc. */
727 #define TLS_TPREL 4 /* TPREL reloc, => IE. */
728 #define TLS_DTPREL 8 /* DTPREL reloc, => LD. */
729 #define TLS_TLS 16 /* Any TLS reloc. */
730 unsigned char tls_mask
;
734 #define IS_TLS_GD(x) (x == (TLS_TLS | TLS_GD))
735 #define IS_TLS_LD(x) (x == (TLS_TLS | TLS_LD))
736 #define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
737 #define IS_TLS_NONE(x) (x == 0)
739 #define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
741 /* ELF linker hash table. */
743 struct elf32_mb_link_hash_table
745 struct elf_link_hash_table elf
;
747 /* TLS Local Dynamic GOT Entry */
749 bfd_signed_vma refcount
;
754 /* Nonzero if this section has TLS related relocations. */
755 #define has_tls_reloc sec_flg0
757 /* Get the ELF linker hash table from a link_info structure. */
759 #define elf32_mb_hash_table(p) \
760 (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
761 == MICROBLAZE_ELF_DATA ? ((struct elf32_mb_link_hash_table *) ((p)->hash)) : NULL)
763 /* Create an entry in a microblaze ELF linker hash table. */
765 static struct bfd_hash_entry
*
766 link_hash_newfunc (struct bfd_hash_entry
*entry
,
767 struct bfd_hash_table
*table
,
770 /* Allocate the structure if it has not already been allocated by a
774 entry
= bfd_hash_allocate (table
,
775 sizeof (struct elf32_mb_link_hash_entry
));
780 /* Call the allocation method of the superclass. */
781 entry
= _bfd_elf_link_hash_newfunc (entry
, table
, string
);
784 struct elf32_mb_link_hash_entry
*eh
;
786 eh
= (struct elf32_mb_link_hash_entry
*) entry
;
793 /* Create a mb ELF linker hash table. */
795 static struct bfd_link_hash_table
*
796 microblaze_elf_link_hash_table_create (bfd
*abfd
)
798 struct elf32_mb_link_hash_table
*ret
;
799 size_t amt
= sizeof (struct elf32_mb_link_hash_table
);
801 ret
= (struct elf32_mb_link_hash_table
*) bfd_zmalloc (amt
);
805 if (!_bfd_elf_link_hash_table_init (&ret
->elf
, abfd
, link_hash_newfunc
,
806 sizeof (struct elf32_mb_link_hash_entry
),
807 MICROBLAZE_ELF_DATA
))
813 return &ret
->elf
.root
;
816 /* Set the values of the small data pointers. */
819 microblaze_elf_final_sdp (struct bfd_link_info
*info
)
821 struct bfd_link_hash_entry
*h
;
823 h
= bfd_link_hash_lookup (info
->hash
, RO_SDA_ANCHOR_NAME
, FALSE
, FALSE
, TRUE
);
824 if (h
!= (struct bfd_link_hash_entry
*) NULL
825 && h
->type
== bfd_link_hash_defined
)
826 ro_small_data_pointer
= (h
->u
.def
.value
827 + h
->u
.def
.section
->output_section
->vma
828 + h
->u
.def
.section
->output_offset
);
830 h
= bfd_link_hash_lookup (info
->hash
, RW_SDA_ANCHOR_NAME
, FALSE
, FALSE
, TRUE
);
831 if (h
!= (struct bfd_link_hash_entry
*) NULL
832 && h
->type
== bfd_link_hash_defined
)
833 rw_small_data_pointer
= (h
->u
.def
.value
834 + h
->u
.def
.section
->output_section
->vma
835 + h
->u
.def
.section
->output_offset
);
839 dtprel_base (struct bfd_link_info
*info
)
841 /* If tls_sec is NULL, we should have signalled an error already. */
842 if (elf_hash_table (info
)->tls_sec
== NULL
)
844 return elf_hash_table (info
)->tls_sec
->vma
;
847 /* The size of the thread control block. */
850 /* Output a simple dynamic relocation into SRELOC. */
853 microblaze_elf_output_dynamic_relocation (bfd
*output_bfd
,
855 unsigned long reloc_index
,
862 Elf_Internal_Rela rel
;
864 rel
.r_info
= ELF32_R_INFO (indx
, r_type
);
865 rel
.r_offset
= offset
;
866 rel
.r_addend
= addend
;
868 bfd_elf32_swap_reloca_out (output_bfd
, &rel
,
869 (sreloc
->contents
+ reloc_index
* sizeof (Elf32_External_Rela
)));
872 /* This code is taken from elf32-m32r.c
873 There is some attempt to make this function usable for many architectures,
874 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
875 if only to serve as a learning tool.
877 The RELOCATE_SECTION function is called by the new ELF backend linker
878 to handle the relocations for a section.
880 The relocs are always passed as Rela structures; if the section
881 actually uses Rel structures, the r_addend field will always be
884 This function is responsible for adjust the section contents as
885 necessary, and (if using Rela relocs and generating a
886 relocatable output file) adjusting the reloc addend as
889 This function does not have to worry about setting the reloc
890 address or the reloc symbol index.
892 LOCAL_SYMS is a pointer to the swapped in local symbols.
894 LOCAL_SECTIONS is an array giving the section in the input file
895 corresponding to the st_shndx field of each local symbol.
897 The global hash table entry for the global symbols can be found
898 via elf_sym_hashes (input_bfd).
900 When generating relocatable output, this function must handle
901 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
902 going to be the section symbol corresponding to the output
903 section, which means that the addend must be adjusted
907 microblaze_elf_relocate_section (bfd
*output_bfd
,
908 struct bfd_link_info
*info
,
910 asection
*input_section
,
912 Elf_Internal_Rela
*relocs
,
913 Elf_Internal_Sym
*local_syms
,
914 asection
**local_sections
)
916 struct elf32_mb_link_hash_table
*htab
;
917 Elf_Internal_Shdr
*symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
918 struct elf_link_hash_entry
**sym_hashes
= elf_sym_hashes (input_bfd
);
919 Elf_Internal_Rela
*rel
, *relend
;
920 int endian
= (bfd_little_endian (output_bfd
)) ? 0 : 2;
921 /* Assume success. */
922 bfd_boolean ret
= TRUE
;
924 bfd_vma
*local_got_offsets
;
925 unsigned int tls_type
;
927 if (!microblaze_elf_howto_table
[R_MICROBLAZE_max
-1])
928 microblaze_elf_howto_init ();
930 htab
= elf32_mb_hash_table (info
);
934 local_got_offsets
= elf_local_got_offsets (input_bfd
);
936 sreloc
= elf_section_data (input_section
)->sreloc
;
939 relend
= relocs
+ input_section
->reloc_count
;
940 for (; rel
< relend
; rel
++)
943 reloc_howto_type
*howto
;
944 unsigned long r_symndx
;
945 bfd_vma addend
= rel
->r_addend
;
946 bfd_vma offset
= rel
->r_offset
;
947 struct elf_link_hash_entry
*h
;
948 Elf_Internal_Sym
*sym
;
950 const char *sym_name
;
951 bfd_reloc_status_type r
= bfd_reloc_ok
;
952 const char *errmsg
= NULL
;
953 bfd_boolean unresolved_reloc
= FALSE
;
956 r_type
= ELF32_R_TYPE (rel
->r_info
);
959 if (r_type
< 0 || r_type
>= (int) R_MICROBLAZE_max
)
961 /* xgettext:c-format */
962 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
963 input_bfd
, (int) r_type
);
964 bfd_set_error (bfd_error_bad_value
);
969 howto
= microblaze_elf_howto_table
[r_type
];
970 r_symndx
= ELF32_R_SYM (rel
->r_info
);
972 if (bfd_link_relocatable (info
))
974 /* This is a relocatable link. We don't have to change
975 anything, unless the reloc is against a section symbol,
976 in which case we have to adjust according to where the
977 section symbol winds up in the output section. */
979 if (r_symndx
>= symtab_hdr
->sh_info
)
980 /* External symbol. */
984 sym
= local_syms
+ r_symndx
;
985 sym_name
= "<local symbol>";
986 /* STT_SECTION: symbol is associated with a section. */
987 if (ELF_ST_TYPE (sym
->st_info
) != STT_SECTION
)
988 /* Symbol isn't associated with a section. Nothing to do. */
991 sec
= local_sections
[r_symndx
];
992 addend
+= sec
->output_offset
+ sym
->st_value
;
994 /* This can't be done for USE_REL because it doesn't mean anything
995 and elf_link_input_bfd asserts this stays zero. */
996 /* rel->r_addend = addend; */
1000 /* Addends are stored with relocs. We're done. */
1003 /* If partial_inplace, we need to store any additional addend
1004 back in the section. */
1005 if (!howto
->partial_inplace
)
1007 /* ??? Here is a nice place to call a special_function like handler. */
1008 r
= _bfd_relocate_contents (howto
, input_bfd
, addend
,
1010 #endif /* USE_REL */
1015 bfd_boolean resolved_to_zero
;
1017 /* This is a final link. */
1020 unresolved_reloc
= FALSE
;
1022 if (r_symndx
< symtab_hdr
->sh_info
)
1025 sym
= local_syms
+ r_symndx
;
1026 sec
= local_sections
[r_symndx
];
1029 sym_name
= "<local symbol>";
1030 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
1031 /* r_addend may have changed if the reference section was
1033 addend
= rel
->r_addend
;
1037 /* External symbol. */
1038 bfd_boolean warned ATTRIBUTE_UNUSED
;
1039 bfd_boolean ignored ATTRIBUTE_UNUSED
;
1041 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
1042 r_symndx
, symtab_hdr
, sym_hashes
,
1044 unresolved_reloc
, warned
, ignored
);
1045 sym_name
= h
->root
.root
.string
;
1048 /* Sanity check the address. */
1049 if (offset
> bfd_get_section_limit (input_bfd
, input_section
))
1051 r
= bfd_reloc_outofrange
;
1055 resolved_to_zero
= (h
!= NULL
1056 && UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
));
1058 switch ((int) r_type
)
1060 case (int) R_MICROBLAZE_SRO32
:
1064 /* Only relocate if the symbol is defined. */
1067 name
= bfd_section_name (sec
);
1069 if (strcmp (name
, ".sdata2") == 0
1070 || strcmp (name
, ".sbss2") == 0)
1072 if (ro_small_data_pointer
== 0)
1073 microblaze_elf_final_sdp (info
);
1074 if (ro_small_data_pointer
== 0)
1077 r
= bfd_reloc_undefined
;
1081 /* At this point `relocation' contains the object's
1083 relocation
-= ro_small_data_pointer
;
1084 /* Now it contains the offset from _SDA2_BASE_. */
1085 r
= _bfd_final_link_relocate (howto
, input_bfd
,
1088 relocation
, addend
);
1093 /* xgettext:c-format */
1094 (_("%pB: the target (%s) of an %s relocation"
1095 " is in the wrong section (%pA)"),
1098 microblaze_elf_howto_table
[(int) r_type
]->name
,
1100 /*bfd_set_error (bfd_error_bad_value); ??? why? */
1108 case (int) R_MICROBLAZE_SRW32
:
1112 /* Only relocate if the symbol is defined. */
1115 name
= bfd_section_name (sec
);
1117 if (strcmp (name
, ".sdata") == 0
1118 || strcmp (name
, ".sbss") == 0)
1120 if (rw_small_data_pointer
== 0)
1121 microblaze_elf_final_sdp (info
);
1122 if (rw_small_data_pointer
== 0)
1125 r
= bfd_reloc_undefined
;
1129 /* At this point `relocation' contains the object's
1131 relocation
-= rw_small_data_pointer
;
1132 /* Now it contains the offset from _SDA_BASE_. */
1133 r
= _bfd_final_link_relocate (howto
, input_bfd
,
1136 relocation
, addend
);
1141 /* xgettext:c-format */
1142 (_("%pB: the target (%s) of an %s relocation"
1143 " is in the wrong section (%pA)"),
1146 microblaze_elf_howto_table
[(int) r_type
]->name
,
1148 /*bfd_set_error (bfd_error_bad_value); ??? why? */
1156 case (int) R_MICROBLAZE_32_SYM_OP_SYM
:
1157 break; /* Do nothing. */
1159 case (int) R_MICROBLAZE_GOTPC_64
:
1160 relocation
= (htab
->elf
.sgotplt
->output_section
->vma
1161 + htab
->elf
.sgotplt
->output_offset
);
1162 relocation
-= (input_section
->output_section
->vma
1163 + input_section
->output_offset
1164 + offset
+ INST_WORD_SIZE
);
1165 relocation
+= addend
;
1166 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1167 contents
+ offset
+ endian
);
1168 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1169 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1172 case (int) R_MICROBLAZE_TEXTPCREL_64
:
1173 relocation
= input_section
->output_section
->vma
;
1174 relocation
-= (input_section
->output_section
->vma
1175 + input_section
->output_offset
1176 + offset
+ INST_WORD_SIZE
);
1177 relocation
+= addend
;
1178 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1179 contents
+ offset
+ endian
);
1180 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1181 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1184 case (int) R_MICROBLAZE_PLT_64
:
1187 if (htab
->elf
.splt
!= NULL
&& h
!= NULL
1188 && h
->plt
.offset
!= (bfd_vma
) -1)
1190 relocation
= (htab
->elf
.splt
->output_section
->vma
1191 + htab
->elf
.splt
->output_offset
1193 unresolved_reloc
= FALSE
;
1194 immediate
= relocation
- (input_section
->output_section
->vma
1195 + input_section
->output_offset
1196 + offset
+ INST_WORD_SIZE
);
1197 bfd_put_16 (input_bfd
, (immediate
>> 16) & 0xffff,
1198 contents
+ offset
+ endian
);
1199 bfd_put_16 (input_bfd
, immediate
& 0xffff,
1200 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1204 relocation
-= (input_section
->output_section
->vma
1205 + input_section
->output_offset
1206 + offset
+ INST_WORD_SIZE
);
1207 immediate
= relocation
;
1208 bfd_put_16 (input_bfd
, (immediate
>> 16) & 0xffff,
1209 contents
+ offset
+ endian
);
1210 bfd_put_16 (input_bfd
, immediate
& 0xffff,
1211 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1216 case (int) R_MICROBLAZE_TLSGD
:
1217 tls_type
= (TLS_TLS
| TLS_GD
);
1219 case (int) R_MICROBLAZE_TLSLD
:
1220 tls_type
= (TLS_TLS
| TLS_LD
);
1223 case (int) R_MICROBLAZE_GOT_64
:
1228 bfd_vma static_value
;
1230 bfd_boolean need_relocs
= FALSE
;
1231 if (htab
->elf
.sgot
== NULL
)
1237 /* 1. Identify GOT Offset;
1238 2. Compute Static Values
1239 3. Process Module Id, Process Offset
1240 4. Fixup Relocation with GOT offset value. */
1242 /* 1. Determine GOT Offset to use : TLS_LD, global, local */
1243 if (IS_TLS_LD (tls_type
))
1244 offp
= &htab
->tlsld_got
.offset
;
1247 if (htab
->elf
.sgotplt
!= NULL
1248 && h
->got
.offset
!= (bfd_vma
) -1)
1249 offp
= &h
->got
.offset
;
1255 if (local_got_offsets
== NULL
)
1257 offp
= &local_got_offsets
[r_symndx
];
1266 if (IS_TLS_LD(tls_type
) || IS_TLS_GD(tls_type
))
1269 /* Symbol index to use for relocs */
1273 elf_hash_table (info
)->dynamic_sections_created
;
1275 if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn
,
1276 bfd_link_pic (info
),
1278 && (!bfd_link_pic (info
)
1279 || !SYMBOL_REFERENCES_LOCAL (info
, h
)))
1283 /* Need to generate relocs ? */
1284 if ((bfd_link_pic (info
) || indx
!= 0)
1286 || (ELF_ST_VISIBILITY (h
->other
) == STV_DEFAULT
1287 && !resolved_to_zero
)
1288 || h
->root
.type
!= bfd_link_hash_undefweak
))
1291 /* 2. Compute/Emit Static value of r-expression */
1292 static_value
= relocation
+ addend
;
1294 /* 3. Process module-id and offset */
1295 if (! ((*offp
) & 1) )
1299 got_offset
= (htab
->elf
.sgot
->output_section
->vma
1300 + htab
->elf
.sgot
->output_offset
1303 /* Process module-id */
1304 if (IS_TLS_LD(tls_type
))
1306 if (! bfd_link_pic (info
))
1307 bfd_put_32 (output_bfd
, 1,
1308 htab
->elf
.sgot
->contents
+ off
);
1310 microblaze_elf_output_dynamic_relocation
1313 htab
->elf
.srelgot
->reloc_count
++,
1314 /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32
,
1317 else if (IS_TLS_GD(tls_type
))
1320 bfd_put_32 (output_bfd
, 1,
1321 htab
->elf
.sgot
->contents
+ off
);
1323 microblaze_elf_output_dynamic_relocation
1326 htab
->elf
.srelgot
->reloc_count
++,
1327 /* symindex= */ indx
, R_MICROBLAZE_TLSDTPMOD32
,
1328 got_offset
, indx
? 0 : static_value
);
1331 /* Process Offset */
1332 if (htab
->elf
.srelgot
== NULL
)
1335 got_offset
= (htab
->elf
.sgot
->output_section
->vma
1336 + htab
->elf
.sgot
->output_offset
1338 if (IS_TLS_LD(tls_type
))
1340 /* For LD, offset should be 0 */
1342 bfd_put_32 (output_bfd
, 0,
1343 htab
->elf
.sgot
->contents
+ off2
);
1345 else if (IS_TLS_GD(tls_type
))
1348 static_value
-= dtprel_base(info
);
1350 microblaze_elf_output_dynamic_relocation
1353 htab
->elf
.srelgot
->reloc_count
++,
1354 /* symindex= */ indx
, R_MICROBLAZE_TLSDTPREL32
,
1355 got_offset
, indx
? 0 : static_value
);
1357 bfd_put_32 (output_bfd
, static_value
,
1358 htab
->elf
.sgot
->contents
+ off2
);
1362 bfd_put_32 (output_bfd
, static_value
,
1363 htab
->elf
.sgot
->contents
+ off2
);
1365 /* Relocs for dyn symbols generated by
1366 finish_dynamic_symbols */
1367 if (bfd_link_pic (info
) && h
== NULL
)
1370 microblaze_elf_output_dynamic_relocation
1373 htab
->elf
.srelgot
->reloc_count
++,
1374 /* symindex= */ indx
, R_MICROBLAZE_REL
,
1375 got_offset
, static_value
);
1380 /* 4. Fixup Relocation with GOT offset value
1381 Compute relative address of GOT entry for applying
1382 the current relocation */
1383 relocation
= htab
->elf
.sgot
->output_section
->vma
1384 + htab
->elf
.sgot
->output_offset
1386 - htab
->elf
.sgotplt
->output_section
->vma
1387 - htab
->elf
.sgotplt
->output_offset
;
1389 /* Apply Current Relocation */
1390 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1391 contents
+ offset
+ endian
);
1392 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1393 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1395 unresolved_reloc
= FALSE
;
1399 case (int) R_MICROBLAZE_GOTOFF_64
:
1402 unsigned short lo
, high
;
1403 relocation
+= addend
;
1404 relocation
-= (htab
->elf
.sgotplt
->output_section
->vma
1405 + htab
->elf
.sgotplt
->output_offset
);
1406 /* Write this value into correct location. */
1407 immediate
= relocation
;
1408 lo
= immediate
& 0x0000ffff;
1409 high
= (immediate
>> 16) & 0x0000ffff;
1410 bfd_put_16 (input_bfd
, high
, contents
+ offset
+ endian
);
1411 bfd_put_16 (input_bfd
, lo
,
1412 contents
+ offset
+ INST_WORD_SIZE
+ endian
);
1416 case (int) R_MICROBLAZE_GOTOFF_32
:
1418 relocation
+= addend
;
1419 relocation
-= (htab
->elf
.sgotplt
->output_section
->vma
1420 + htab
->elf
.sgotplt
->output_offset
);
1421 /* Write this value into correct location. */
1422 bfd_put_32 (input_bfd
, relocation
, contents
+ offset
);
1426 case (int) R_MICROBLAZE_TLSDTPREL64
:
1427 relocation
+= addend
;
1428 relocation
-= dtprel_base(info
);
1429 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1430 contents
+ offset
+ 2);
1431 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1432 contents
+ offset
+ 2 + INST_WORD_SIZE
);
1434 case (int) R_MICROBLAZE_TEXTREL_64
:
1435 case (int) R_MICROBLAZE_TEXTREL_32_LO
:
1436 case (int) R_MICROBLAZE_64_PCREL
:
1437 case (int) R_MICROBLAZE_64
:
1438 case (int) R_MICROBLAZE_32
:
1440 /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
1441 from removed linkonce sections, or sections discarded by
1443 if (r_symndx
== STN_UNDEF
|| (input_section
->flags
& SEC_ALLOC
) == 0)
1445 relocation
+= addend
;
1446 if (r_type
== R_MICROBLAZE_32
)
1447 bfd_put_32 (input_bfd
, relocation
, contents
+ offset
);
1450 if (r_type
== R_MICROBLAZE_64_PCREL
)
1451 relocation
-= (input_section
->output_section
->vma
1452 + input_section
->output_offset
1453 + offset
+ INST_WORD_SIZE
);
1454 else if (r_type
== R_MICROBLAZE_TEXTREL_64
1455 || r_type
== R_MICROBLAZE_TEXTREL_32_LO
)
1456 relocation
-= input_section
->output_section
->vma
;
1458 if (r_type
== R_MICROBLAZE_TEXTREL_32_LO
)
1459 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1460 contents
+ offset
+ endian
);
1464 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1465 contents
+ offset
+ endian
);
1466 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1467 contents
+ offset
+ endian
+ INST_WORD_SIZE
);
1473 if ((bfd_link_pic (info
)
1475 || (ELF_ST_VISIBILITY (h
->other
) == STV_DEFAULT
1476 && !resolved_to_zero
)
1477 || h
->root
.type
!= bfd_link_hash_undefweak
)
1478 && (!howto
->pc_relative
1482 || !h
->def_regular
))))
1483 || (!bfd_link_pic (info
)
1489 || h
->root
.type
== bfd_link_hash_undefweak
1490 || h
->root
.type
== bfd_link_hash_undefined
)))
1492 Elf_Internal_Rela outrel
;
1496 /* When generating a shared object, these relocations
1497 are copied into the output file to be resolved at run
1500 BFD_ASSERT (sreloc
!= NULL
);
1505 _bfd_elf_section_offset (output_bfd
, info
, input_section
,
1507 if (outrel
.r_offset
== (bfd_vma
) -1)
1509 else if (outrel
.r_offset
== (bfd_vma
) -2)
1511 outrel
.r_offset
+= (input_section
->output_section
->vma
1512 + input_section
->output_offset
);
1515 memset (&outrel
, 0, sizeof outrel
);
1516 /* h->dynindx may be -1 if the symbol was marked to
1519 && ((! info
->symbolic
&& h
->dynindx
!= -1)
1520 || !h
->def_regular
))
1522 BFD_ASSERT (h
->dynindx
!= -1);
1523 outrel
.r_info
= ELF32_R_INFO (h
->dynindx
, r_type
);
1524 outrel
.r_addend
= addend
;
1528 if (r_type
== R_MICROBLAZE_32
)
1530 outrel
.r_info
= ELF32_R_INFO (0, R_MICROBLAZE_REL
);
1531 outrel
.r_addend
= relocation
+ addend
;
1537 (_("%pB: probably compiled without -fPIC?"),
1539 bfd_set_error (bfd_error_bad_value
);
1544 loc
= sreloc
->contents
;
1545 loc
+= sreloc
->reloc_count
++ * sizeof (Elf32_External_Rela
);
1546 bfd_elf32_swap_reloca_out (output_bfd
, &outrel
, loc
);
1551 relocation
+= addend
;
1552 if (r_type
== R_MICROBLAZE_32
)
1553 bfd_put_32 (input_bfd
, relocation
, contents
+ offset
);
1556 if (r_type
== R_MICROBLAZE_64_PCREL
)
1557 relocation
-= (input_section
->output_section
->vma
1558 + input_section
->output_offset
1559 + offset
+ INST_WORD_SIZE
);
1560 else if (r_type
== R_MICROBLAZE_TEXTREL_64
1561 || r_type
== R_MICROBLAZE_TEXTREL_32_LO
)
1562 relocation
-= input_section
->output_section
->vma
;
1564 if (r_type
== R_MICROBLAZE_TEXTREL_32_LO
)
1566 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1567 contents
+ offset
+ endian
);
1571 bfd_put_16 (input_bfd
, (relocation
>> 16) & 0xffff,
1572 contents
+ offset
+ endian
);
1573 bfd_put_16 (input_bfd
, relocation
& 0xffff,
1574 contents
+ offset
+ endian
1583 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
1585 relocation
, addend
);
1592 if (r
!= bfd_reloc_ok
)
1594 /* FIXME: This should be generic enough to go in a utility. */
1598 name
= h
->root
.root
.string
;
1601 name
= (bfd_elf_string_from_elf_section
1602 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
1603 if (name
== NULL
|| *name
== '\0')
1604 name
= bfd_section_name (sec
);
1612 case bfd_reloc_overflow
:
1613 (*info
->callbacks
->reloc_overflow
)
1614 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
1615 (bfd_vma
) 0, input_bfd
, input_section
, offset
);
1618 case bfd_reloc_undefined
:
1619 (*info
->callbacks
->undefined_symbol
)
1620 (info
, name
, input_bfd
, input_section
, offset
, TRUE
);
1623 case bfd_reloc_outofrange
:
1624 errmsg
= _("internal error: out of range error");
1627 case bfd_reloc_notsupported
:
1628 errmsg
= _("internal error: unsupported relocation error");
1631 case bfd_reloc_dangerous
:
1632 errmsg
= _("internal error: dangerous error");
1636 errmsg
= _("internal error: unknown error");
1639 (*info
->callbacks
->warning
) (info
, errmsg
, name
, input_bfd
,
1640 input_section
, offset
);
1649 /* Calculate fixup value for reference. */
1652 calc_fixup (bfd_vma start
, bfd_vma size
, asection
*sec
)
1654 bfd_vma end
= start
+ size
;
1657 if (sec
== NULL
|| sec
->relax
== NULL
)
1660 /* Look for addr in relax table, total fixup value. */
1661 for (i
= 0; i
< sec
->relax_count
; i
++)
1663 if (end
<= sec
->relax
[i
].addr
)
1665 if ((end
!= start
) && (start
> sec
->relax
[i
].addr
))
1667 fixup
+= sec
->relax
[i
].size
;
1672 /* Read-modify-write into the bfd, an immediate value into appropriate fields of
1673 a 32-bit instruction. */
1675 microblaze_bfd_write_imm_value_32 (bfd
*abfd
, bfd_byte
*bfd_addr
, bfd_vma val
)
1677 unsigned long instr
= bfd_get_32 (abfd
, bfd_addr
);
1678 instr
&= ~0x0000ffff;
1679 instr
|= (val
& 0x0000ffff);
1680 bfd_put_32 (abfd
, instr
, bfd_addr
);
1683 /* Read-modify-write into the bfd, an immediate value into appropriate fields of
1684 two consecutive 32-bit instructions. */
1686 microblaze_bfd_write_imm_value_64 (bfd
*abfd
, bfd_byte
*bfd_addr
, bfd_vma val
)
1688 unsigned long instr_hi
;
1689 unsigned long instr_lo
;
1691 instr_hi
= bfd_get_32 (abfd
, bfd_addr
);
1692 instr_hi
&= ~0x0000ffff;
1693 instr_hi
|= ((val
>> 16) & 0x0000ffff);
1694 bfd_put_32 (abfd
, instr_hi
, bfd_addr
);
1696 instr_lo
= bfd_get_32 (abfd
, bfd_addr
+ INST_WORD_SIZE
);
1697 instr_lo
&= ~0x0000ffff;
1698 instr_lo
|= (val
& 0x0000ffff);
1699 bfd_put_32 (abfd
, instr_lo
, bfd_addr
+ INST_WORD_SIZE
);
1703 microblaze_elf_relax_section (bfd
*abfd
,
1705 struct bfd_link_info
*link_info
,
1708 Elf_Internal_Shdr
*symtab_hdr
;
1709 Elf_Internal_Rela
*internal_relocs
;
1710 Elf_Internal_Rela
*free_relocs
= NULL
;
1711 Elf_Internal_Rela
*irel
, *irelend
;
1712 bfd_byte
*contents
= NULL
;
1713 bfd_byte
*free_contents
= NULL
;
1718 struct elf_link_hash_entry
*sym_hash
;
1719 Elf_Internal_Sym
*isymbuf
, *isymend
;
1720 Elf_Internal_Sym
*isym
;
1725 /* We only do this once per section. We may be able to delete some code
1726 by running multiple passes, but it is not worth it. */
1729 /* Only do this for a text section. */
1730 if (bfd_link_relocatable (link_info
)
1731 || (sec
->flags
& SEC_RELOC
) == 0
1732 || (sec
->reloc_count
== 0)
1733 || (sec
->flags
& SEC_CODE
) == 0)
1736 BFD_ASSERT ((sec
->size
> 0) || (sec
->rawsize
> 0));
1738 /* If this is the first time we have been called for this section,
1739 initialize the cooked size. */
1741 sec
->size
= sec
->rawsize
;
1743 /* Get symbols for this section. */
1744 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
1745 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
1746 symcount
= symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
);
1747 if (isymbuf
== NULL
)
1748 isymbuf
= bfd_elf_get_elf_syms (abfd
, symtab_hdr
, symcount
,
1749 0, NULL
, NULL
, NULL
);
1750 BFD_ASSERT (isymbuf
!= NULL
);
1752 internal_relocs
= _bfd_elf_link_read_relocs (abfd
, sec
, NULL
, NULL
, link_info
->keep_memory
);
1753 if (internal_relocs
== NULL
)
1755 if (! link_info
->keep_memory
)
1756 free_relocs
= internal_relocs
;
1758 sec
->relax
= (struct relax_table
*) bfd_malloc ((sec
->reloc_count
+ 1)
1759 * sizeof (struct relax_table
));
1760 if (sec
->relax
== NULL
)
1762 sec
->relax_count
= 0;
1764 irelend
= internal_relocs
+ sec
->reloc_count
;
1766 for (irel
= internal_relocs
; irel
< irelend
; irel
++, rel_count
++)
1769 if ((ELF32_R_TYPE (irel
->r_info
) != (int) R_MICROBLAZE_64_PCREL
)
1770 && (ELF32_R_TYPE (irel
->r_info
) != (int) R_MICROBLAZE_64
)
1771 && (ELF32_R_TYPE (irel
->r_info
) != (int) R_MICROBLAZE_TEXTREL_64
))
1772 continue; /* Can't delete this reloc. */
1774 /* Get the section contents. */
1775 if (contents
== NULL
)
1777 if (elf_section_data (sec
)->this_hdr
.contents
!= NULL
)
1778 contents
= elf_section_data (sec
)->this_hdr
.contents
;
1781 contents
= (bfd_byte
*) bfd_malloc (sec
->size
);
1782 if (contents
== NULL
)
1784 free_contents
= contents
;
1786 if (!bfd_get_section_contents (abfd
, sec
, contents
,
1787 (file_ptr
) 0, sec
->size
))
1789 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1793 /* Get the value of the symbol referred to by the reloc. */
1794 if (ELF32_R_SYM (irel
->r_info
) < symtab_hdr
->sh_info
)
1796 /* A local symbol. */
1799 isym
= isymbuf
+ ELF32_R_SYM (irel
->r_info
);
1800 if (isym
->st_shndx
== SHN_UNDEF
)
1801 sym_sec
= bfd_und_section_ptr
;
1802 else if (isym
->st_shndx
== SHN_ABS
)
1803 sym_sec
= bfd_abs_section_ptr
;
1804 else if (isym
->st_shndx
== SHN_COMMON
)
1805 sym_sec
= bfd_com_section_ptr
;
1807 sym_sec
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
1809 symval
= _bfd_elf_rela_local_sym (abfd
, isym
, &sym_sec
, irel
);
1814 struct elf_link_hash_entry
*h
;
1816 indx
= ELF32_R_SYM (irel
->r_info
) - symtab_hdr
->sh_info
;
1817 h
= elf_sym_hashes (abfd
)[indx
];
1818 BFD_ASSERT (h
!= NULL
);
1820 if (h
->root
.type
!= bfd_link_hash_defined
1821 && h
->root
.type
!= bfd_link_hash_defweak
)
1822 /* This appears to be a reference to an undefined
1823 symbol. Just ignore it--it will be caught by the
1824 regular reloc processing. */
1827 symval
= (h
->root
.u
.def
.value
1828 + h
->root
.u
.def
.section
->output_section
->vma
1829 + h
->root
.u
.def
.section
->output_offset
);
1832 /* If this is a PC-relative reloc, subtract the instr offset from
1833 the symbol value. */
1834 if (ELF32_R_TYPE (irel
->r_info
) == (int) R_MICROBLAZE_64_PCREL
)
1836 symval
= symval
+ irel
->r_addend
1838 + sec
->output_section
->vma
1839 + sec
->output_offset
);
1841 else if (ELF32_R_TYPE (irel
->r_info
) == (int) R_MICROBLAZE_TEXTREL_64
)
1843 symval
= symval
+ irel
->r_addend
- (sec
->output_section
->vma
);
1846 symval
+= irel
->r_addend
;
1848 if ((symval
& 0xffff8000) == 0
1849 || (symval
& 0xffff8000) == 0xffff8000)
1851 /* We can delete this instruction. */
1852 sec
->relax
[sec
->relax_count
].addr
= irel
->r_offset
;
1853 sec
->relax
[sec
->relax_count
].size
= INST_WORD_SIZE
;
1856 /* Rewrite relocation type. */
1857 switch ((enum elf_microblaze_reloc_type
) ELF32_R_TYPE (irel
->r_info
))
1859 case R_MICROBLAZE_64_PCREL
:
1860 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1861 (int) R_MICROBLAZE_32_PCREL_LO
);
1863 case R_MICROBLAZE_64
:
1864 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1865 (int) R_MICROBLAZE_32_LO
);
1867 case R_MICROBLAZE_TEXTREL_64
:
1868 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1869 (int) R_MICROBLAZE_TEXTREL_32_LO
);
1872 /* Cannot happen. */
1876 } /* Loop through all relocations. */
1878 /* Loop through the relocs again, and see if anything needs to change. */
1879 if (sec
->relax_count
> 0)
1881 shndx
= _bfd_elf_section_from_bfd_section (abfd
, sec
);
1883 sec
->relax
[sec
->relax_count
].addr
= sec
->size
;
1885 for (irel
= internal_relocs
; irel
< irelend
; irel
++, rel_count
++)
1889 /* Get the new reloc address. */
1890 nraddr
= irel
->r_offset
- calc_fixup (irel
->r_offset
, 0, sec
);
1891 switch ((enum elf_microblaze_reloc_type
) ELF32_R_TYPE (irel
->r_info
))
1895 case R_MICROBLAZE_64_PCREL
:
1897 case R_MICROBLAZE_TEXTREL_64
:
1898 case R_MICROBLAZE_TEXTREL_32_LO
:
1899 case R_MICROBLAZE_64
:
1900 case R_MICROBLAZE_32_LO
:
1901 /* If this reloc is against a symbol defined in this
1902 section, we must check the addend to see it will put the value in
1903 range to be adjusted, and hence must be changed. */
1904 if (ELF32_R_SYM (irel
->r_info
) < symtab_hdr
->sh_info
)
1906 isym
= isymbuf
+ ELF32_R_SYM (irel
->r_info
);
1907 /* Only handle relocs against .text. */
1908 if (isym
->st_shndx
== shndx
1909 && ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
)
1910 irel
->r_addend
-= calc_fixup (irel
->r_addend
, 0, sec
);
1913 case R_MICROBLAZE_NONE
:
1915 /* This was a PC-relative instruction that was
1916 completely resolved. */
1918 bfd_vma target_address
;
1919 target_address
= irel
->r_addend
+ irel
->r_offset
;
1920 sfix
= calc_fixup (irel
->r_offset
, 0, sec
);
1921 efix
= calc_fixup (target_address
, 0, sec
);
1922 irel
->r_addend
-= (efix
- sfix
);
1923 /* Should use HOWTO. */
1924 microblaze_bfd_write_imm_value_32 (abfd
, contents
+ irel
->r_offset
,
1928 case R_MICROBLAZE_64_NONE
:
1930 /* This was a PC-relative 64-bit instruction that was
1931 completely resolved. */
1933 bfd_vma target_address
;
1934 target_address
= irel
->r_addend
+ irel
->r_offset
+ INST_WORD_SIZE
;
1935 sfix
= calc_fixup (irel
->r_offset
+ INST_WORD_SIZE
, 0, sec
);
1936 efix
= calc_fixup (target_address
, 0, sec
);
1937 irel
->r_addend
-= (efix
- sfix
);
1938 microblaze_bfd_write_imm_value_32 (abfd
, contents
+ irel
->r_offset
1939 + INST_WORD_SIZE
, irel
->r_addend
);
1943 irel
->r_offset
= nraddr
;
1944 } /* Change all relocs in this section. */
1946 /* Look through all other sections. */
1947 for (o
= abfd
->sections
; o
!= NULL
; o
= o
->next
)
1949 Elf_Internal_Rela
*irelocs
;
1950 Elf_Internal_Rela
*irelscan
, *irelscanend
;
1951 bfd_byte
*ocontents
;
1954 || (o
->flags
& SEC_RELOC
) == 0
1955 || o
->reloc_count
== 0)
1958 /* We always cache the relocs. Perhaps, if info->keep_memory is
1959 FALSE, we should free them, if we are permitted to. */
1961 irelocs
= _bfd_elf_link_read_relocs (abfd
, o
, NULL
, NULL
, TRUE
);
1962 if (irelocs
== NULL
)
1966 irelscanend
= irelocs
+ o
->reloc_count
;
1967 for (irelscan
= irelocs
; irelscan
< irelscanend
; irelscan
++)
1969 if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_32
)
1971 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
1973 /* Look at the reloc only if the value has been resolved. */
1974 if (isym
->st_shndx
== shndx
1975 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
1977 if (ocontents
== NULL
)
1979 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
1980 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
1983 /* We always cache the section contents.
1984 Perhaps, if info->keep_memory is FALSE, we
1985 should free them, if we are permitted to. */
1986 if (o
->rawsize
== 0)
1987 o
->rawsize
= o
->size
;
1988 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
1989 if (ocontents
== NULL
)
1991 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
1995 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
1999 irelscan
->r_addend
-= calc_fixup (irelscan
->r_addend
, 0, sec
);
2001 else if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_32_SYM_OP_SYM
)
2003 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2005 /* Look at the reloc only if the value has been resolved. */
2006 if (ocontents
== NULL
)
2008 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2009 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2012 /* We always cache the section contents.
2013 Perhaps, if info->keep_memory is FALSE, we
2014 should free them, if we are permitted to. */
2016 if (o
->rawsize
== 0)
2017 o
->rawsize
= o
->size
;
2018 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2019 if (ocontents
== NULL
)
2021 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2025 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2028 irelscan
->r_addend
-= calc_fixup (irel
->r_addend
2034 else if ((ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_32_PCREL_LO
)
2035 || (ELF32_R_TYPE (irelscan
->r_info
)
2036 == (int) R_MICROBLAZE_32_LO
)
2037 || (ELF32_R_TYPE (irelscan
->r_info
)
2038 == (int) R_MICROBLAZE_TEXTREL_32_LO
))
2040 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2042 /* Look at the reloc only if the value has been resolved. */
2043 if (isym
->st_shndx
== shndx
2044 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
2047 bfd_vma target_address
;
2049 if (ocontents
== NULL
)
2051 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2052 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2055 /* We always cache the section contents.
2056 Perhaps, if info->keep_memory is FALSE, we
2057 should free them, if we are permitted to. */
2058 if (o
->rawsize
== 0)
2059 o
->rawsize
= o
->size
;
2060 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2061 if (ocontents
== NULL
)
2063 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2067 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2071 unsigned long instr
= bfd_get_32 (abfd
, ocontents
+ irelscan
->r_offset
);
2072 immediate
= instr
& 0x0000ffff;
2073 target_address
= immediate
;
2074 offset
= calc_fixup (target_address
, 0, sec
);
2075 immediate
-= offset
;
2076 irelscan
->r_addend
-= offset
;
2077 microblaze_bfd_write_imm_value_32 (abfd
, ocontents
+ irelscan
->r_offset
,
2078 irelscan
->r_addend
);
2082 if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_64
2083 || (ELF32_R_TYPE (irelscan
->r_info
)
2084 == (int) R_MICROBLAZE_TEXTREL_64
))
2086 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2088 /* Look at the reloc only if the value has been resolved. */
2089 if (isym
->st_shndx
== shndx
2090 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
2094 if (ocontents
== NULL
)
2096 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2097 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2100 /* We always cache the section contents.
2101 Perhaps, if info->keep_memory is FALSE, we
2102 should free them, if we are permitted to. */
2104 if (o
->rawsize
== 0)
2105 o
->rawsize
= o
->size
;
2106 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2107 if (ocontents
== NULL
)
2109 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2113 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2116 unsigned long instr_hi
= bfd_get_32 (abfd
, ocontents
2117 + irelscan
->r_offset
);
2118 unsigned long instr_lo
= bfd_get_32 (abfd
, ocontents
2119 + irelscan
->r_offset
2121 immediate
= (instr_hi
& 0x0000ffff) << 16;
2122 immediate
|= (instr_lo
& 0x0000ffff);
2123 offset
= calc_fixup (irelscan
->r_addend
, 0, sec
);
2124 immediate
-= offset
;
2125 irelscan
->r_addend
-= offset
;
2128 else if (ELF32_R_TYPE (irelscan
->r_info
) == (int) R_MICROBLAZE_64_PCREL
)
2130 isym
= isymbuf
+ ELF32_R_SYM (irelscan
->r_info
);
2132 /* Look at the reloc only if the value has been resolved. */
2133 if (isym
->st_shndx
== shndx
2134 && (ELF32_ST_TYPE (isym
->st_info
) == STT_SECTION
))
2137 bfd_vma target_address
;
2139 if (ocontents
== NULL
)
2141 if (elf_section_data (o
)->this_hdr
.contents
!= NULL
)
2142 ocontents
= elf_section_data (o
)->this_hdr
.contents
;
2145 /* We always cache the section contents.
2146 Perhaps, if info->keep_memory is FALSE, we
2147 should free them, if we are permitted to. */
2148 if (o
->rawsize
== 0)
2149 o
->rawsize
= o
->size
;
2150 ocontents
= (bfd_byte
*) bfd_malloc (o
->rawsize
);
2151 if (ocontents
== NULL
)
2153 if (!bfd_get_section_contents (abfd
, o
, ocontents
,
2157 elf_section_data (o
)->this_hdr
.contents
= ocontents
;
2160 unsigned long instr_hi
= bfd_get_32 (abfd
, ocontents
2161 + irelscan
->r_offset
);
2162 unsigned long instr_lo
= bfd_get_32 (abfd
, ocontents
2163 + irelscan
->r_offset
2165 immediate
= (instr_hi
& 0x0000ffff) << 16;
2166 immediate
|= (instr_lo
& 0x0000ffff);
2167 target_address
= immediate
;
2168 offset
= calc_fixup (target_address
, 0, sec
);
2169 immediate
-= offset
;
2170 irelscan
->r_addend
-= offset
;
2171 microblaze_bfd_write_imm_value_64 (abfd
, ocontents
2172 + irelscan
->r_offset
, immediate
);
2178 /* Adjust the local symbols defined in this section. */
2179 isymend
= isymbuf
+ symtab_hdr
->sh_info
;
2180 for (isym
= isymbuf
; isym
< isymend
; isym
++)
2182 if (isym
->st_shndx
== shndx
)
2184 isym
->st_value
-= calc_fixup (isym
->st_value
, 0, sec
);
2186 isym
->st_size
-= calc_fixup (isym
->st_value
, isym
->st_size
, sec
);
2190 /* Now adjust the global symbols defined in this section. */
2191 isym
= isymbuf
+ symtab_hdr
->sh_info
;
2192 symcount
= (symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
)) - symtab_hdr
->sh_info
;
2193 for (sym_index
= 0; sym_index
< symcount
; sym_index
++)
2195 sym_hash
= elf_sym_hashes (abfd
)[sym_index
];
2196 if ((sym_hash
->root
.type
== bfd_link_hash_defined
2197 || sym_hash
->root
.type
== bfd_link_hash_defweak
)
2198 && sym_hash
->root
.u
.def
.section
== sec
)
2200 sym_hash
->root
.u
.def
.value
-= calc_fixup (sym_hash
->root
.u
.def
.value
,
2203 sym_hash
->size
-= calc_fixup (sym_hash
->root
.u
.def
.value
,
2204 sym_hash
->size
, sec
);
2208 /* Physically move the code and change the cooked size. */
2209 dest
= sec
->relax
[0].addr
;
2210 for (i
= 0; i
< sec
->relax_count
; i
++)
2213 src
= sec
->relax
[i
].addr
+ sec
->relax
[i
].size
;
2214 len
= sec
->relax
[i
+1].addr
- sec
->relax
[i
].addr
- sec
->relax
[i
].size
;
2216 memmove (contents
+ dest
, contents
+ src
, len
);
2217 sec
->size
-= sec
->relax
[i
].size
;
2221 elf_section_data (sec
)->relocs
= internal_relocs
;
2224 elf_section_data (sec
)->this_hdr
.contents
= contents
;
2225 free_contents
= NULL
;
2227 symtab_hdr
->contents
= (bfd_byte
*) isymbuf
;
2233 if (free_contents
!= NULL
)
2235 if (!link_info
->keep_memory
)
2236 free (free_contents
);
2238 /* Cache the section contents for elf_link_input_bfd. */
2239 elf_section_data (sec
)->this_hdr
.contents
= contents
;
2240 free_contents
= NULL
;
2243 if (sec
->relax_count
== 0)
2255 free (free_contents
);
2258 sec
->relax_count
= 0;
2262 /* Return the section that should be marked against GC for a given
2266 microblaze_elf_gc_mark_hook (asection
*sec
,
2267 struct bfd_link_info
* info
,
2268 Elf_Internal_Rela
* rel
,
2269 struct elf_link_hash_entry
* h
,
2270 Elf_Internal_Sym
* sym
)
2273 switch (ELF32_R_TYPE (rel
->r_info
))
2275 case R_MICROBLAZE_GNU_VTINHERIT
:
2276 case R_MICROBLAZE_GNU_VTENTRY
:
2280 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
2285 #define PLT_ENTRY_SIZE 16
2287 #define PLT_ENTRY_WORD_0 0xb0000000 /* "imm 0". */
2288 #define PLT_ENTRY_WORD_1 0xe9940000 /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT. */
2289 #define PLT_ENTRY_WORD_1_NOPIC 0xe9800000 /* "lwi r12,r0,0" - non-PIC object. */
2290 #define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
2291 #define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
2294 update_local_sym_info (bfd
*abfd
,
2295 Elf_Internal_Shdr
*symtab_hdr
,
2296 unsigned long r_symndx
,
2297 unsigned int tls_type
)
2299 bfd_signed_vma
*local_got_refcounts
= elf_local_got_refcounts (abfd
);
2300 unsigned char *local_got_tls_masks
;
2302 if (local_got_refcounts
== NULL
)
2304 bfd_size_type size
= symtab_hdr
->sh_info
;
2306 size
*= (sizeof (*local_got_refcounts
) + sizeof (*local_got_tls_masks
));
2307 local_got_refcounts
= bfd_zalloc (abfd
, size
);
2308 if (local_got_refcounts
== NULL
)
2310 elf_local_got_refcounts (abfd
) = local_got_refcounts
;
2313 local_got_tls_masks
=
2314 (unsigned char *) (local_got_refcounts
+ symtab_hdr
->sh_info
);
2315 local_got_tls_masks
[r_symndx
] |= tls_type
;
2316 local_got_refcounts
[r_symndx
] += 1;
2320 /* Look through the relocs for a section during the first phase. */
2323 microblaze_elf_check_relocs (bfd
* abfd
,
2324 struct bfd_link_info
* info
,
2326 const Elf_Internal_Rela
* relocs
)
2328 Elf_Internal_Shdr
* symtab_hdr
;
2329 struct elf_link_hash_entry
** sym_hashes
;
2330 struct elf_link_hash_entry
** sym_hashes_end
;
2331 const Elf_Internal_Rela
* rel
;
2332 const Elf_Internal_Rela
* rel_end
;
2333 struct elf32_mb_link_hash_table
*htab
;
2334 asection
*sreloc
= NULL
;
2336 if (bfd_link_relocatable (info
))
2339 htab
= elf32_mb_hash_table (info
);
2343 symtab_hdr
= & elf_tdata (abfd
)->symtab_hdr
;
2344 sym_hashes
= elf_sym_hashes (abfd
);
2345 sym_hashes_end
= sym_hashes
+ symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
);
2346 if (!elf_bad_symtab (abfd
))
2347 sym_hashes_end
-= symtab_hdr
->sh_info
;
2349 rel_end
= relocs
+ sec
->reloc_count
;
2351 for (rel
= relocs
; rel
< rel_end
; rel
++)
2353 unsigned int r_type
;
2354 struct elf_link_hash_entry
* h
;
2355 unsigned long r_symndx
;
2356 unsigned char tls_type
= 0;
2358 r_symndx
= ELF32_R_SYM (rel
->r_info
);
2359 r_type
= ELF32_R_TYPE (rel
->r_info
);
2361 if (r_symndx
< symtab_hdr
->sh_info
)
2365 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
2366 while (h
->root
.type
== bfd_link_hash_indirect
2367 || h
->root
.type
== bfd_link_hash_warning
)
2368 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
2373 /* This relocation describes the C++ object vtable hierarchy.
2374 Reconstruct it for later use during GC. */
2375 case R_MICROBLAZE_GNU_VTINHERIT
:
2376 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
2380 /* This relocation describes which C++ vtable entries are actually
2381 used. Record for later use during GC. */
2382 case R_MICROBLAZE_GNU_VTENTRY
:
2383 if (!bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
2387 /* This relocation requires .plt entry. */
2388 case R_MICROBLAZE_PLT_64
:
2392 h
->plt
.refcount
+= 1;
2396 /* This relocation requires .got entry. */
2397 case R_MICROBLAZE_TLSGD
:
2398 tls_type
|= (TLS_TLS
| TLS_GD
);
2400 case R_MICROBLAZE_TLSLD
:
2401 tls_type
|= (TLS_TLS
| TLS_LD
);
2404 sec
->has_tls_reloc
= 1;
2406 case R_MICROBLAZE_GOT_64
:
2407 if (htab
->elf
.sgot
== NULL
)
2409 if (htab
->elf
.dynobj
== NULL
)
2410 htab
->elf
.dynobj
= abfd
;
2411 if (!_bfd_elf_create_got_section (htab
->elf
.dynobj
, info
))
2416 h
->got
.refcount
+= 1;
2417 elf32_mb_hash_entry (h
)->tls_mask
|= tls_type
;
2421 if (! update_local_sym_info(abfd
, symtab_hdr
, r_symndx
, tls_type
) )
2426 case R_MICROBLAZE_GOTOFF_64
:
2427 case R_MICROBLAZE_GOTOFF_32
:
2428 if (htab
->elf
.sgot
== NULL
)
2430 if (htab
->elf
.dynobj
== NULL
)
2431 htab
->elf
.dynobj
= abfd
;
2432 if (!_bfd_elf_create_got_section (htab
->elf
.dynobj
, info
))
2437 case R_MICROBLAZE_64
:
2438 case R_MICROBLAZE_64_PCREL
:
2439 case R_MICROBLAZE_32
:
2441 if (h
!= NULL
&& !bfd_link_pic (info
))
2443 /* we may need a copy reloc. */
2446 /* we may also need a .plt entry. */
2447 h
->plt
.refcount
+= 1;
2448 if (ELF32_R_TYPE (rel
->r_info
) != R_MICROBLAZE_64_PCREL
)
2449 h
->pointer_equality_needed
= 1;
2453 /* If we are creating a shared library, and this is a reloc
2454 against a global symbol, or a non PC relative reloc
2455 against a local symbol, then we need to copy the reloc
2456 into the shared library. However, if we are linking with
2457 -Bsymbolic, we do not need to copy a reloc against a
2458 global symbol which is defined in an object we are
2459 including in the link (i.e., DEF_REGULAR is set). At
2460 this point we have not seen all the input files, so it is
2461 possible that DEF_REGULAR is not set now but will be set
2462 later (it is never cleared). In case of a weak definition,
2463 DEF_REGULAR may be cleared later by a strong definition in
2464 a shared library. We account for that possibility below by
2465 storing information in the relocs_copied field of the hash
2466 table entry. A similar situation occurs when creating
2467 shared libraries and symbol visibility changes render the
2470 If on the other hand, we are creating an executable, we
2471 may need to keep relocations for symbols satisfied by a
2472 dynamic library if we manage to avoid copy relocs for the
2475 if ((bfd_link_pic (info
)
2476 && (sec
->flags
& SEC_ALLOC
) != 0
2477 && (r_type
!= R_MICROBLAZE_64_PCREL
2479 && (! info
->symbolic
2480 || h
->root
.type
== bfd_link_hash_defweak
2481 || !h
->def_regular
))))
2482 || (!bfd_link_pic (info
)
2483 && (sec
->flags
& SEC_ALLOC
) != 0
2485 && (h
->root
.type
== bfd_link_hash_defweak
2486 || !h
->def_regular
)))
2488 struct elf_dyn_relocs
*p
;
2489 struct elf_dyn_relocs
**head
;
2491 /* When creating a shared object, we must copy these
2492 relocs into the output file. We create a reloc
2493 section in dynobj and make room for the reloc. */
2499 if (htab
->elf
.dynobj
== NULL
)
2500 htab
->elf
.dynobj
= abfd
;
2501 dynobj
= htab
->elf
.dynobj
;
2503 sreloc
= _bfd_elf_make_dynamic_reloc_section (sec
, dynobj
,
2509 /* If this is a global symbol, we count the number of
2510 relocations we need for this symbol. */
2512 head
= &h
->dyn_relocs
;
2515 /* Track dynamic relocs needed for local syms too.
2516 We really need local syms available to do this
2520 Elf_Internal_Sym
*isym
;
2523 isym
= bfd_sym_from_r_symndx (&htab
->elf
.sym_cache
,
2528 s
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
2532 vpp
= &elf_section_data (s
)->local_dynrel
;
2533 head
= (struct elf_dyn_relocs
**) vpp
;
2537 if (p
== NULL
|| p
->sec
!= sec
)
2539 size_t amt
= sizeof *p
;
2540 p
= ((struct elf_dyn_relocs
*)
2541 bfd_alloc (htab
->elf
.dynobj
, amt
));
2552 if (r_type
== R_MICROBLAZE_64_PCREL
)
2563 /* Copy the extra info we tack onto an elf_link_hash_entry. */
2566 microblaze_elf_copy_indirect_symbol (struct bfd_link_info
*info
,
2567 struct elf_link_hash_entry
*dir
,
2568 struct elf_link_hash_entry
*ind
)
2570 struct elf32_mb_link_hash_entry
*edir
, *eind
;
2572 edir
= (struct elf32_mb_link_hash_entry
*) dir
;
2573 eind
= (struct elf32_mb_link_hash_entry
*) ind
;
2575 edir
->tls_mask
|= eind
->tls_mask
;
2577 _bfd_elf_link_hash_copy_indirect (info
, dir
, ind
);
2581 microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info
*info
,
2582 struct elf_link_hash_entry
*h
)
2584 struct elf32_mb_link_hash_table
*htab
;
2586 unsigned int power_of_two
;
2588 htab
= elf32_mb_hash_table (info
);
2592 /* If this is a function, put it in the procedure linkage table. We
2593 will fill in the contents of the procedure linkage table later,
2594 when we know the address of the .got section. */
2595 if (h
->type
== STT_FUNC
2598 if (h
->plt
.refcount
<= 0
2599 || SYMBOL_CALLS_LOCAL (info
, h
)
2600 || (ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
2601 && h
->root
.type
== bfd_link_hash_undefweak
))
2603 /* This case can occur if we saw a PLT reloc in an input
2604 file, but the symbol was never referred to by a dynamic
2605 object, or if all references were garbage collected. In
2606 such a case, we don't actually need to build a procedure
2607 linkage table, and we can just do a PC32 reloc instead. */
2608 h
->plt
.offset
= (bfd_vma
) -1;
2615 /* It's possible that we incorrectly decided a .plt reloc was
2616 needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
2617 check_relocs. We can't decide accurately between function and
2618 non-function syms in check-relocs; Objects loaded later in
2619 the link may change h->type. So fix it now. */
2620 h
->plt
.offset
= (bfd_vma
) -1;
2622 /* If this is a weak symbol, and there is a real definition, the
2623 processor independent code will have arranged for us to see the
2624 real definition first, and we can just use the same value. */
2625 if (h
->is_weakalias
)
2627 struct elf_link_hash_entry
*def
= weakdef (h
);
2628 BFD_ASSERT (def
->root
.type
== bfd_link_hash_defined
);
2629 h
->root
.u
.def
.section
= def
->root
.u
.def
.section
;
2630 h
->root
.u
.def
.value
= def
->root
.u
.def
.value
;
2634 /* This is a reference to a symbol defined by a dynamic object which
2635 is not a function. */
2637 /* If we are creating a shared library, we must presume that the
2638 only references to the symbol are via the global offset table.
2639 For such cases we need not do anything here; the relocations will
2640 be handled correctly by relocate_section. */
2641 if (bfd_link_pic (info
))
2644 /* If there are no references to this symbol that do not use the
2645 GOT, we don't need to generate a copy reloc. */
2646 if (!h
->non_got_ref
)
2649 /* If -z nocopyreloc was given, we won't generate them either. */
2650 if (info
->nocopyreloc
)
2656 /* If we don't find any dynamic relocs in read-only sections, then
2657 we'll be keeping the dynamic relocs and avoiding the copy reloc. */
2658 if (!_bfd_elf_readonly_dynrelocs (h
))
2664 /* We must allocate the symbol in our .dynbss section, which will
2665 become part of the .bss section of the executable. There will be
2666 an entry for this symbol in the .dynsym section. The dynamic
2667 object will contain position independent code, so all references
2668 from the dynamic object to this symbol will go through the global
2669 offset table. The dynamic linker will use the .dynsym entry to
2670 determine the address it must put in the global offset table, so
2671 both the dynamic object and the regular object will refer to the
2672 same memory location for the variable. */
2674 /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
2675 to copy the initial value out of the dynamic object and into the
2676 runtime process image. */
2677 if ((h
->root
.u
.def
.section
->flags
& SEC_READONLY
) != 0)
2679 s
= htab
->elf
.sdynrelro
;
2680 srel
= htab
->elf
.sreldynrelro
;
2684 s
= htab
->elf
.sdynbss
;
2685 srel
= htab
->elf
.srelbss
;
2687 if ((h
->root
.u
.def
.section
->flags
& SEC_ALLOC
) != 0)
2689 srel
->size
+= sizeof (Elf32_External_Rela
);
2693 /* We need to figure out the alignment required for this symbol. I
2694 have no idea how ELF linkers handle this. */
2695 power_of_two
= bfd_log2 (h
->size
);
2696 if (power_of_two
> 3)
2699 /* Apply the required alignment. */
2700 s
->size
= BFD_ALIGN (s
->size
, (bfd_size_type
) (1 << power_of_two
));
2701 if (power_of_two
> s
->alignment_power
)
2703 if (!bfd_set_section_alignment (s
, power_of_two
))
2707 /* Define the symbol as being at this point in the section. */
2708 h
->root
.u
.def
.section
= s
;
2709 h
->root
.u
.def
.value
= s
->size
;
2711 /* Increment the section size to make room for the symbol. */
2716 /* Allocate space in .plt, .got and associated reloc sections for
2720 allocate_dynrelocs (struct elf_link_hash_entry
*h
, void * dat
)
2722 struct bfd_link_info
*info
;
2723 struct elf32_mb_link_hash_table
*htab
;
2724 struct elf32_mb_link_hash_entry
*eh
;
2725 struct elf_dyn_relocs
*p
;
2727 if (h
->root
.type
== bfd_link_hash_indirect
)
2730 info
= (struct bfd_link_info
*) dat
;
2731 htab
= elf32_mb_hash_table (info
);
2735 if (htab
->elf
.dynamic_sections_created
2736 && h
->plt
.refcount
> 0)
2738 /* Make sure this symbol is output as a dynamic symbol.
2739 Undefined weak syms won't yet be marked as dynamic. */
2740 if (h
->dynindx
== -1
2741 && !h
->forced_local
)
2743 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2747 if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info
), h
))
2749 asection
*s
= htab
->elf
.splt
;
2751 /* The first entry in .plt is reserved. */
2753 s
->size
= PLT_ENTRY_SIZE
;
2755 h
->plt
.offset
= s
->size
;
2757 /* If this symbol is not defined in a regular file, and we are
2758 not generating a shared library, then set the symbol to this
2759 location in the .plt. This is required to make function
2760 pointers compare as equal between the normal executable and
2761 the shared library. */
2762 if (! bfd_link_pic (info
)
2765 h
->root
.u
.def
.section
= s
;
2766 h
->root
.u
.def
.value
= h
->plt
.offset
;
2769 /* Make room for this entry. */
2770 s
->size
+= PLT_ENTRY_SIZE
;
2772 /* We also need to make an entry in the .got.plt section, which
2773 will be placed in the .got section by the linker script. */
2774 htab
->elf
.sgotplt
->size
+= 4;
2776 /* We also need to make an entry in the .rel.plt section. */
2777 htab
->elf
.srelplt
->size
+= sizeof (Elf32_External_Rela
);
2781 h
->plt
.offset
= (bfd_vma
) -1;
2787 h
->plt
.offset
= (bfd_vma
) -1;
2791 eh
= (struct elf32_mb_link_hash_entry
*) h
;
2792 if (h
->got
.refcount
> 0)
2797 /* Make sure this symbol is output as a dynamic symbol.
2798 Undefined weak syms won't yet be marked as dynamic. */
2799 if (h
->dynindx
== -1
2800 && !h
->forced_local
)
2802 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2807 if ((eh
->tls_mask
& TLS_TLS
) != 0)
2809 /* Handle TLS Symbol */
2810 if ((eh
->tls_mask
& TLS_LD
) != 0)
2812 if (!eh
->elf
.def_dynamic
)
2813 /* We'll just use htab->tlsld_got.offset. This should
2814 always be the case. It's a little odd if we have
2815 a local dynamic reloc against a non-local symbol. */
2816 htab
->tlsld_got
.refcount
+= 1;
2820 if ((eh
->tls_mask
& TLS_GD
) != 0)
2825 /* Regular (non-TLS) symbol */
2830 h
->got
.offset
= (bfd_vma
) -1;
2835 h
->got
.offset
= s
->size
;
2837 htab
->elf
.srelgot
->size
+= need
* (sizeof (Elf32_External_Rela
) / 4);
2841 h
->got
.offset
= (bfd_vma
) -1;
2843 if (h
->dyn_relocs
== NULL
)
2846 /* In the shared -Bsymbolic case, discard space allocated for
2847 dynamic pc-relative relocs against symbols which turn out to be
2848 defined in regular objects. For the normal shared case, discard
2849 space for pc-relative relocs that have become local due to symbol
2850 visibility changes. */
2852 if (bfd_link_pic (info
))
2858 struct elf_dyn_relocs
**pp
;
2860 for (pp
= &h
->dyn_relocs
; (p
= *pp
) != NULL
; )
2862 p
->count
-= p
->pc_count
;
2870 else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
2871 h
->dyn_relocs
= NULL
;
2875 /* For the non-shared case, discard space for relocs against
2876 symbols which turn out to need copy relocs or are not
2882 || (htab
->elf
.dynamic_sections_created
2883 && (h
->root
.type
== bfd_link_hash_undefweak
2884 || h
->root
.type
== bfd_link_hash_undefined
))))
2886 /* Make sure this symbol is output as a dynamic symbol.
2887 Undefined weak syms won't yet be marked as dynamic. */
2888 if (h
->dynindx
== -1
2889 && !h
->forced_local
)
2891 if (! bfd_elf_link_record_dynamic_symbol (info
, h
))
2895 /* If that succeeded, we know we'll be keeping all the
2897 if (h
->dynindx
!= -1)
2901 h
->dyn_relocs
= NULL
;
2906 /* Finally, allocate space. */
2907 for (p
= h
->dyn_relocs
; p
!= NULL
; p
= p
->next
)
2909 asection
*sreloc
= elf_section_data (p
->sec
)->sreloc
;
2910 sreloc
->size
+= p
->count
* sizeof (Elf32_External_Rela
);
2916 /* Set the sizes of the dynamic sections. */
2919 microblaze_elf_size_dynamic_sections (bfd
*output_bfd ATTRIBUTE_UNUSED
,
2920 struct bfd_link_info
*info
)
2922 struct elf32_mb_link_hash_table
*htab
;
2927 htab
= elf32_mb_hash_table (info
);
2931 dynobj
= htab
->elf
.dynobj
;
2932 BFD_ASSERT (dynobj
!= NULL
);
2934 /* Set up .got offsets for local syms, and space for local dynamic
2936 for (ibfd
= info
->input_bfds
; ibfd
!= NULL
; ibfd
= ibfd
->link
.next
)
2938 bfd_signed_vma
*local_got
;
2939 bfd_signed_vma
*end_local_got
;
2940 bfd_size_type locsymcount
;
2941 Elf_Internal_Shdr
*symtab_hdr
;
2942 unsigned char *lgot_masks
;
2945 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
)
2948 for (s
= ibfd
->sections
; s
!= NULL
; s
= s
->next
)
2950 struct elf_dyn_relocs
*p
;
2952 for (p
= ((struct elf_dyn_relocs
*)
2953 elf_section_data (s
)->local_dynrel
);
2957 if (!bfd_is_abs_section (p
->sec
)
2958 && bfd_is_abs_section (p
->sec
->output_section
))
2960 /* Input section has been discarded, either because
2961 it is a copy of a linkonce section or due to
2962 linker script /DISCARD/, so we'll be discarding
2965 else if (p
->count
!= 0)
2967 srel
= elf_section_data (p
->sec
)->sreloc
;
2968 srel
->size
+= p
->count
* sizeof (Elf32_External_Rela
);
2969 if ((p
->sec
->output_section
->flags
& SEC_READONLY
) != 0)
2970 info
->flags
|= DF_TEXTREL
;
2975 local_got
= elf_local_got_refcounts (ibfd
);
2979 symtab_hdr
= &elf_tdata (ibfd
)->symtab_hdr
;
2980 locsymcount
= symtab_hdr
->sh_info
;
2981 end_local_got
= local_got
+ locsymcount
;
2982 lgot_masks
= (unsigned char *) end_local_got
;
2984 srel
= htab
->elf
.srelgot
;
2986 for (; local_got
< end_local_got
; ++local_got
, ++lgot_masks
)
2990 unsigned int need
= 0;
2991 if ((*lgot_masks
& TLS_TLS
) != 0)
2993 if ((*lgot_masks
& TLS_GD
) != 0)
2995 if ((*lgot_masks
& TLS_LD
) != 0)
2996 htab
->tlsld_got
.refcount
+= 1;
3003 *local_got
= (bfd_vma
) -1;
3007 *local_got
= s
->size
;
3009 if (bfd_link_pic (info
))
3010 srel
->size
+= need
* (sizeof (Elf32_External_Rela
) / 4);
3014 *local_got
= (bfd_vma
) -1;
3018 /* Allocate global sym .plt and .got entries, and space for global
3019 sym dynamic relocs. */
3020 elf_link_hash_traverse (elf_hash_table (info
), allocate_dynrelocs
, info
);
3022 if (htab
->tlsld_got
.refcount
> 0)
3024 htab
->tlsld_got
.offset
= htab
->elf
.sgot
->size
;
3025 htab
->elf
.sgot
->size
+= 8;
3026 if (bfd_link_pic (info
))
3027 htab
->elf
.srelgot
->size
+= sizeof (Elf32_External_Rela
);
3030 htab
->tlsld_got
.offset
= (bfd_vma
) -1;
3032 if (elf_hash_table (info
)->dynamic_sections_created
)
3034 /* Make space for the trailing nop in .plt. */
3035 if (htab
->elf
.splt
->size
> 0)
3036 htab
->elf
.splt
->size
+= 4;
3039 /* The check_relocs and adjust_dynamic_symbol entry points have
3040 determined the sizes of the various dynamic sections. Allocate
3042 for (s
= dynobj
->sections
; s
!= NULL
; s
= s
->next
)
3045 bfd_boolean strip
= FALSE
;
3047 if ((s
->flags
& SEC_LINKER_CREATED
) == 0)
3050 /* It's OK to base decisions on the section name, because none
3051 of the dynobj section names depend upon the input files. */
3052 name
= bfd_section_name (s
);
3054 if (strncmp (name
, ".rela", 5) == 0)
3058 /* If we don't need this section, strip it from the
3059 output file. This is to handle .rela.bss and
3060 .rela.plt. We must create it in
3061 create_dynamic_sections, because it must be created
3062 before the linker maps input sections to output
3063 sections. The linker does that before
3064 adjust_dynamic_symbol is called, and it is that
3065 function which decides whether anything needs to go
3066 into these sections. */
3071 /* We use the reloc_count field as a counter if we need
3072 to copy relocs into the output file. */
3076 else if (s
!= htab
->elf
.splt
3077 && s
!= htab
->elf
.sgot
3078 && s
!= htab
->elf
.sgotplt
3079 && s
!= htab
->elf
.sdynbss
3080 && s
!= htab
->elf
.sdynrelro
)
3082 /* It's not one of our sections, so don't allocate space. */
3088 s
->flags
|= SEC_EXCLUDE
;
3092 /* Allocate memory for the section contents. */
3093 /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
3094 Unused entries should be reclaimed before the section's contents
3095 are written out, but at the moment this does not happen. Thus in
3096 order to prevent writing out garbage, we initialise the section's
3097 contents to zero. */
3098 s
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, s
->size
);
3099 if (s
->contents
== NULL
&& s
->size
!= 0)
3103 /* ??? Force DF_BIND_NOW? */
3104 info
->flags
|= DF_BIND_NOW
;
3105 return _bfd_elf_add_dynamic_tags (output_bfd
, info
, TRUE
);
3108 /* Finish up dynamic symbol handling. We set the contents of various
3109 dynamic sections here. */
3112 microblaze_elf_finish_dynamic_symbol (bfd
*output_bfd
,
3113 struct bfd_link_info
*info
,
3114 struct elf_link_hash_entry
*h
,
3115 Elf_Internal_Sym
*sym
)
3117 struct elf32_mb_link_hash_table
*htab
;
3118 struct elf32_mb_link_hash_entry
*eh
= elf32_mb_hash_entry(h
);
3120 htab
= elf32_mb_hash_table (info
);
3124 if (h
->plt
.offset
!= (bfd_vma
) -1)
3129 Elf_Internal_Rela rela
;
3135 /* This symbol has an entry in the procedure linkage table. Set
3137 BFD_ASSERT (h
->dynindx
!= -1);
3139 splt
= htab
->elf
.splt
;
3140 srela
= htab
->elf
.srelplt
;
3141 sgotplt
= htab
->elf
.sgotplt
;
3142 BFD_ASSERT (splt
!= NULL
&& srela
!= NULL
&& sgotplt
!= NULL
);
3144 plt_index
= h
->plt
.offset
/ PLT_ENTRY_SIZE
- 1; /* first entry reserved. */
3145 got_offset
= (plt_index
+ 3) * 4; /* 3 reserved ??? */
3146 got_addr
= got_offset
;
3148 /* For non-PIC objects we need absolute address of the GOT entry. */
3149 if (!bfd_link_pic (info
))
3150 got_addr
+= sgotplt
->output_section
->vma
+ sgotplt
->output_offset
;
3152 /* Fill in the entry in the procedure linkage table. */
3153 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_0
+ ((got_addr
>> 16) & 0xffff),
3154 splt
->contents
+ h
->plt
.offset
);
3155 if (bfd_link_pic (info
))
3156 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_1
+ (got_addr
& 0xffff),
3157 splt
->contents
+ h
->plt
.offset
+ 4);
3159 bfd_put_32 (output_bfd
, PLT_ENTRY_WORD_1_NOPIC
+ (got_addr
& 0xffff),
3160 splt
->contents
+ h
->plt
.offset
+ 4);
3161 bfd_put_32 (output_bfd
, (bfd_vma
) PLT_ENTRY_WORD_2
,
3162 splt
->contents
+ h
->plt
.offset
+ 8);
3163 bfd_put_32 (output_bfd
, (bfd_vma
) PLT_ENTRY_WORD_3
,
3164 splt
->contents
+ h
->plt
.offset
+ 12);
3166 /* Any additions to the .got section??? */
3167 /* bfd_put_32 (output_bfd,
3168 splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
3169 sgotplt->contents + got_offset); */
3171 /* Fill in the entry in the .rela.plt section. */
3172 rela
.r_offset
= (sgotplt
->output_section
->vma
3173 + sgotplt
->output_offset
3175 rela
.r_info
= ELF32_R_INFO (h
->dynindx
, R_MICROBLAZE_JUMP_SLOT
);
3177 loc
= srela
->contents
;
3178 loc
+= plt_index
* sizeof (Elf32_External_Rela
);
3179 bfd_elf32_swap_reloca_out (output_bfd
, &rela
, loc
);
3181 if (!h
->def_regular
)
3183 /* Mark the symbol as undefined, rather than as defined in
3184 the .plt section. Zero the value. */
3185 sym
->st_shndx
= SHN_UNDEF
;
3190 /* h->got.refcount to be checked ? */
3191 if (h
->got
.offset
!= (bfd_vma
) -1 &&
3192 ! ((h
->got
.offset
& 1) ||
3193 IS_TLS_LD(eh
->tls_mask
) || IS_TLS_GD(eh
->tls_mask
)))
3199 /* This symbol has an entry in the global offset table. Set it
3202 sgot
= htab
->elf
.sgot
;
3203 srela
= htab
->elf
.srelgot
;
3204 BFD_ASSERT (sgot
!= NULL
&& srela
!= NULL
);
3206 offset
= (sgot
->output_section
->vma
+ sgot
->output_offset
3207 + (h
->got
.offset
&~ (bfd_vma
) 1));
3209 /* If this is a -Bsymbolic link, and the symbol is defined
3210 locally, we just want to emit a RELATIVE reloc. Likewise if
3211 the symbol was forced to be local because of a version file.
3212 The entry in the global offset table will already have been
3213 initialized in the relocate_section function. */
3214 if (bfd_link_pic (info
)
3215 && ((info
->symbolic
&& h
->def_regular
)
3216 || h
->dynindx
== -1))
3218 asection
*sec
= h
->root
.u
.def
.section
;
3221 value
= h
->root
.u
.def
.value
;
3222 if (sec
->output_section
!= NULL
)
3223 /* PR 21180: If the output section is NULL, then the symbol is no
3224 longer needed, and in theory the GOT entry is redundant. But
3225 it is too late to change our minds now... */
3226 value
+= sec
->output_section
->vma
+ sec
->output_offset
;
3228 microblaze_elf_output_dynamic_relocation (output_bfd
,
3229 srela
, srela
->reloc_count
++,
3231 R_MICROBLAZE_REL
, offset
,
3236 microblaze_elf_output_dynamic_relocation (output_bfd
,
3237 srela
, srela
->reloc_count
++,
3239 R_MICROBLAZE_GLOB_DAT
,
3243 bfd_put_32 (output_bfd
, (bfd_vma
) 0,
3244 sgot
->contents
+ (h
->got
.offset
&~ (bfd_vma
) 1));
3250 Elf_Internal_Rela rela
;
3253 /* This symbols needs a copy reloc. Set it up. */
3255 BFD_ASSERT (h
->dynindx
!= -1);
3257 rela
.r_offset
= (h
->root
.u
.def
.value
3258 + h
->root
.u
.def
.section
->output_section
->vma
3259 + h
->root
.u
.def
.section
->output_offset
);
3260 rela
.r_info
= ELF32_R_INFO (h
->dynindx
, R_MICROBLAZE_COPY
);
3262 if (h
->root
.u
.def
.section
== htab
->elf
.sdynrelro
)
3263 s
= htab
->elf
.sreldynrelro
;
3265 s
= htab
->elf
.srelbss
;
3266 loc
= s
->contents
+ s
->reloc_count
++ * sizeof (Elf32_External_Rela
);
3267 bfd_elf32_swap_reloca_out (output_bfd
, &rela
, loc
);
3270 /* Mark some specially defined symbols as absolute. */
3271 if (h
== htab
->elf
.hdynamic
3272 || h
== htab
->elf
.hgot
3273 || h
== htab
->elf
.hplt
)
3274 sym
->st_shndx
= SHN_ABS
;
3280 /* Finish up the dynamic sections. */
3283 microblaze_elf_finish_dynamic_sections (bfd
*output_bfd
,
3284 struct bfd_link_info
*info
)
3287 asection
*sdyn
, *sgot
;
3288 struct elf32_mb_link_hash_table
*htab
;
3290 htab
= elf32_mb_hash_table (info
);
3294 dynobj
= htab
->elf
.dynobj
;
3296 sdyn
= bfd_get_linker_section (dynobj
, ".dynamic");
3298 if (htab
->elf
.dynamic_sections_created
)
3301 Elf32_External_Dyn
*dyncon
, *dynconend
;
3303 dyncon
= (Elf32_External_Dyn
*) sdyn
->contents
;
3304 dynconend
= (Elf32_External_Dyn
*) (sdyn
->contents
+ sdyn
->size
);
3305 for (; dyncon
< dynconend
; dyncon
++)
3307 Elf_Internal_Dyn dyn
;
3311 bfd_elf32_swap_dyn_in (dynobj
, dyncon
, &dyn
);
3316 s
= htab
->elf
.sgotplt
;
3321 s
= htab
->elf
.srelplt
;
3326 s
= htab
->elf
.srelplt
;
3339 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
3341 dyn
.d_un
.d_val
= s
->size
;
3343 bfd_elf32_swap_dyn_out (output_bfd
, &dyn
, dyncon
);
3346 splt
= htab
->elf
.splt
;
3347 BFD_ASSERT (splt
!= NULL
&& sdyn
!= NULL
);
3349 /* Clear the first entry in the procedure linkage table,
3350 and put a nop in the last four bytes. */
3353 memset (splt
->contents
, 0, PLT_ENTRY_SIZE
);
3354 bfd_put_32 (output_bfd
, (bfd_vma
) 0x80000000 /* nop. */,
3355 splt
->contents
+ splt
->size
- 4);
3357 if (splt
->output_section
!= bfd_abs_section_ptr
)
3358 elf_section_data (splt
->output_section
)->this_hdr
.sh_entsize
= 4;
3362 /* Set the first entry in the global offset table to the address of
3363 the dynamic section. */
3364 sgot
= htab
->elf
.sgotplt
;
3365 if (sgot
&& sgot
->size
> 0)
3368 bfd_put_32 (output_bfd
, (bfd_vma
) 0, sgot
->contents
);
3370 bfd_put_32 (output_bfd
,
3371 sdyn
->output_section
->vma
+ sdyn
->output_offset
,
3373 elf_section_data (sgot
->output_section
)->this_hdr
.sh_entsize
= 4;
3376 if (htab
->elf
.sgot
&& htab
->elf
.sgot
->size
> 0)
3377 elf_section_data (htab
->elf
.sgot
->output_section
)->this_hdr
.sh_entsize
= 4;
3382 /* Hook called by the linker routine which adds symbols from an object
3383 file. We use it to put .comm items in .sbss, and not .bss. */
3386 microblaze_elf_add_symbol_hook (bfd
*abfd
,
3387 struct bfd_link_info
*info
,
3388 Elf_Internal_Sym
*sym
,
3389 const char **namep ATTRIBUTE_UNUSED
,
3390 flagword
*flagsp ATTRIBUTE_UNUSED
,
3394 if (sym
->st_shndx
== SHN_COMMON
3395 && !bfd_link_relocatable (info
)
3396 && sym
->st_size
<= elf_gp_size (abfd
))
3398 /* Common symbols less than or equal to -G nn bytes are automatically
3400 *secp
= bfd_make_section_old_way (abfd
, ".sbss");
3402 || !bfd_set_section_flags (*secp
, SEC_IS_COMMON
| SEC_SMALL_DATA
))
3405 *valp
= sym
->st_size
;
3411 #define TARGET_LITTLE_SYM microblaze_elf32_le_vec
3412 #define TARGET_LITTLE_NAME "elf32-microblazeel"
3414 #define TARGET_BIG_SYM microblaze_elf32_vec
3415 #define TARGET_BIG_NAME "elf32-microblaze"
3417 #define ELF_ARCH bfd_arch_microblaze
3418 #define ELF_TARGET_ID MICROBLAZE_ELF_DATA
3419 #define ELF_MACHINE_CODE EM_MICROBLAZE
3420 #define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
3421 #define ELF_MAXPAGESIZE 0x1000
3422 #define elf_info_to_howto microblaze_elf_info_to_howto
3423 #define elf_info_to_howto_rel NULL
3425 #define bfd_elf32_bfd_reloc_type_lookup microblaze_elf_reloc_type_lookup
3426 #define bfd_elf32_bfd_is_local_label_name microblaze_elf_is_local_label_name
3427 #define elf_backend_relocate_section microblaze_elf_relocate_section
3428 #define bfd_elf32_bfd_relax_section microblaze_elf_relax_section
3429 #define bfd_elf32_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
3430 #define bfd_elf32_bfd_reloc_name_lookup microblaze_elf_reloc_name_lookup
3432 #define elf_backend_gc_mark_hook microblaze_elf_gc_mark_hook
3433 #define elf_backend_check_relocs microblaze_elf_check_relocs
3434 #define elf_backend_copy_indirect_symbol microblaze_elf_copy_indirect_symbol
3435 #define bfd_elf32_bfd_link_hash_table_create microblaze_elf_link_hash_table_create
3436 #define elf_backend_can_gc_sections 1
3437 #define elf_backend_can_refcount 1
3438 #define elf_backend_want_got_plt 1
3439 #define elf_backend_plt_readonly 1
3440 #define elf_backend_got_header_size 12
3441 #define elf_backend_want_dynrelro 1
3442 #define elf_backend_rela_normal 1
3443 #define elf_backend_dtrel_excludes_plt 1
3445 #define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
3446 #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
3447 #define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
3448 #define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
3449 #define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections
3450 #define elf_backend_add_symbol_hook microblaze_elf_add_symbol_hook
3452 #include "elf32-target.h"