Implement tp_richcompare for gdb.Block
[binutils-gdb.git] / bfd / elf32-microblaze.c
blobce2064a75df18dd0d8b099b0512d9822f44423b7
1 /* Xilinx MicroBlaze-specific support for 32-bit ELF
3 Copyright (C) 2009-2024 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. */
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "bfdlink.h"
26 #include "libbfd.h"
27 #include "elf-bfd.h"
28 #include "elf/microblaze.h"
29 #include <assert.h>
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. */
44 0, /* Rightshift. */
45 0, /* Size. */
46 0, /* Bitsize. */
47 false, /* PC_relative. */
48 0, /* Bitpos. */
49 complain_overflow_dont, /* Complain on overflow. */
50 NULL, /* Special Function. */
51 "R_MICROBLAZE_NONE", /* Name. */
52 false, /* Partial Inplace. */
53 0, /* Source Mask. */
54 0, /* Dest Mask. */
55 false), /* PC relative offset? */
57 /* A standard 32 bit relocation. */
58 HOWTO (R_MICROBLAZE_32, /* Type. */
59 0, /* Rightshift. */
60 4, /* Size. */
61 32, /* Bitsize. */
62 false, /* PC_relative. */
63 0, /* Bitpos. */
64 complain_overflow_bitfield, /* Complain on overflow. */
65 bfd_elf_generic_reloc,/* Special Function. */
66 "R_MICROBLAZE_32", /* Name. */
67 false, /* Partial Inplace. */
68 0, /* Source Mask. */
69 0xffffffff, /* Dest Mask. */
70 false), /* PC relative offset? */
72 /* A standard PCREL 32 bit relocation. */
73 HOWTO (R_MICROBLAZE_32_PCREL,/* Type. */
74 0, /* Rightshift. */
75 4, /* Size. */
76 32, /* Bitsize. */
77 true, /* PC_relative. */
78 0, /* Bitpos. */
79 complain_overflow_bitfield, /* Complain on overflow. */
80 bfd_elf_generic_reloc,/* Special Function. */
81 "R_MICROBLAZE_32_PCREL", /* Name. */
82 true, /* Partial Inplace. */
83 0, /* Source Mask. */
84 0xffffffff, /* Dest Mask. */
85 true), /* PC relative offset? */
87 /* A 64 bit PCREL relocation. Table-entry not really used. */
88 HOWTO (R_MICROBLAZE_64_PCREL,/* Type. */
89 0, /* Rightshift. */
90 4, /* Size. */
91 16, /* Bitsize. */
92 true, /* PC_relative. */
93 0, /* Bitpos. */
94 complain_overflow_dont, /* Complain on overflow. */
95 bfd_elf_generic_reloc,/* Special Function. */
96 "R_MICROBLAZE_64_PCREL", /* Name. */
97 false, /* Partial Inplace. */
98 0, /* Source Mask. */
99 0x0000ffff, /* Dest Mask. */
100 true), /* PC relative offset? */
102 /* The low half of a PCREL 32 bit relocation. */
103 HOWTO (R_MICROBLAZE_32_PCREL_LO, /* Type. */
104 0, /* Rightshift. */
105 4, /* Size. */
106 16, /* Bitsize. */
107 true, /* PC_relative. */
108 0, /* Bitpos. */
109 complain_overflow_signed, /* Complain on overflow. */
110 bfd_elf_generic_reloc, /* Special Function. */
111 "R_MICROBLAZE_32_PCREL_LO", /* Name. */
112 false, /* Partial Inplace. */
113 0, /* Source Mask. */
114 0x0000ffff, /* Dest Mask. */
115 true), /* PC relative offset? */
117 /* A 64 bit relocation. Table entry not really used. */
118 HOWTO (R_MICROBLAZE_64, /* Type. */
119 0, /* Rightshift. */
120 4, /* Size. */
121 16, /* Bitsize. */
122 false, /* PC_relative. */
123 0, /* Bitpos. */
124 complain_overflow_dont, /* Complain on overflow. */
125 bfd_elf_generic_reloc,/* Special Function. */
126 "R_MICROBLAZE_64", /* Name. */
127 false, /* Partial Inplace. */
128 0, /* Source Mask. */
129 0x0000ffff, /* Dest Mask. */
130 false), /* PC relative offset? */
132 /* The low half of a 32 bit relocation. */
133 HOWTO (R_MICROBLAZE_32_LO, /* Type. */
134 0, /* Rightshift. */
135 4, /* Size. */
136 16, /* Bitsize. */
137 false, /* PC_relative. */
138 0, /* Bitpos. */
139 complain_overflow_signed, /* Complain on overflow. */
140 bfd_elf_generic_reloc,/* Special Function. */
141 "R_MICROBLAZE_32_LO", /* Name. */
142 false, /* Partial Inplace. */
143 0, /* Source Mask. */
144 0x0000ffff, /* Dest Mask. */
145 false), /* PC relative offset? */
147 /* Read-only small data section relocation. */
148 HOWTO (R_MICROBLAZE_SRO32, /* Type. */
149 0, /* Rightshift. */
150 4, /* Size. */
151 16, /* Bitsize. */
152 false, /* PC_relative. */
153 0, /* Bitpos. */
154 complain_overflow_bitfield, /* Complain on overflow. */
155 bfd_elf_generic_reloc,/* Special Function. */
156 "R_MICROBLAZE_SRO32", /* Name. */
157 false, /* Partial Inplace. */
158 0, /* Source Mask. */
159 0x0000ffff, /* Dest Mask. */
160 false), /* PC relative offset? */
162 /* Read-write small data area relocation. */
163 HOWTO (R_MICROBLAZE_SRW32, /* Type. */
164 0, /* Rightshift. */
165 4, /* Size. */
166 16, /* Bitsize. */
167 false, /* PC_relative. */
168 0, /* Bitpos. */
169 complain_overflow_bitfield, /* Complain on overflow. */
170 bfd_elf_generic_reloc,/* Special Function. */
171 "R_MICROBLAZE_SRW32", /* Name. */
172 false, /* Partial Inplace. */
173 0, /* Source Mask. */
174 0x0000ffff, /* Dest Mask. */
175 false), /* PC relative offset? */
177 /* This reloc does nothing. Used for relaxation. */
178 HOWTO (R_MICROBLAZE_32_NONE, /* Type. */
179 0, /* Rightshift. */
180 2, /* Size (0 = byte, 1 = short, 2 = long). */
181 32, /* Bitsize. */
182 true, /* PC_relative. */
183 0, /* Bitpos. */
184 complain_overflow_bitfield, /* Complain on overflow. */
185 NULL, /* Special Function. */
186 "R_MICROBLAZE_32_NONE", /* Name. */
187 false, /* Partial Inplace. */
188 0, /* Source Mask. */
189 0, /* Dest Mask. */
190 false), /* PC relative offset? */
192 /* This reloc does nothing. Used for relaxation. */
193 HOWTO (R_MICROBLAZE_64_NONE, /* Type. */
194 0, /* Rightshift. */
195 0, /* Size. */
196 0, /* Bitsize. */
197 true, /* PC_relative. */
198 0, /* Bitpos. */
199 complain_overflow_dont, /* Complain on overflow. */
200 NULL, /* Special Function. */
201 "R_MICROBLAZE_64_NONE",/* Name. */
202 false, /* Partial Inplace. */
203 0, /* Source Mask. */
204 0, /* Dest Mask. */
205 false), /* PC relative offset? */
207 /* Symbol Op Symbol relocation. */
208 HOWTO (R_MICROBLAZE_32_SYM_OP_SYM, /* Type. */
209 0, /* Rightshift. */
210 4, /* Size. */
211 32, /* Bitsize. */
212 false, /* PC_relative. */
213 0, /* Bitpos. */
214 complain_overflow_bitfield, /* Complain on overflow. */
215 bfd_elf_generic_reloc,/* Special Function. */
216 "R_MICROBLAZE_32_SYM_OP_SYM", /* Name. */
217 false, /* Partial Inplace. */
218 0, /* Source Mask. */
219 0xffffffff, /* Dest Mask. */
220 false), /* PC relative offset? */
222 /* GNU extension to record C++ vtable hierarchy. */
223 HOWTO (R_MICROBLAZE_GNU_VTINHERIT, /* Type. */
224 0, /* Rightshift. */
225 4, /* Size. */
226 0, /* Bitsize. */
227 false, /* PC_relative. */
228 0, /* Bitpos. */
229 complain_overflow_dont,/* Complain on overflow. */
230 NULL, /* Special Function. */
231 "R_MICROBLAZE_GNU_VTINHERIT", /* Name. */
232 false, /* Partial Inplace. */
233 0, /* Source Mask. */
234 0, /* Dest Mask. */
235 false), /* PC relative offset? */
237 /* GNU extension to record C++ vtable member usage. */
238 HOWTO (R_MICROBLAZE_GNU_VTENTRY, /* Type. */
239 0, /* Rightshift. */
240 4, /* Size. */
241 0, /* Bitsize. */
242 false, /* PC_relative. */
243 0, /* Bitpos. */
244 complain_overflow_dont,/* Complain on overflow. */
245 _bfd_elf_rel_vtable_reloc_fn, /* Special Function. */
246 "R_MICROBLAZE_GNU_VTENTRY", /* Name. */
247 false, /* Partial Inplace. */
248 0, /* Source Mask. */
249 0, /* Dest Mask. */
250 false), /* PC relative offset? */
252 /* A 64 bit GOTPC relocation. Table-entry not really used. */
253 HOWTO (R_MICROBLAZE_GOTPC_64, /* Type. */
254 0, /* Rightshift. */
255 4, /* Size. */
256 16, /* Bitsize. */
257 true, /* PC_relative. */
258 0, /* Bitpos. */
259 complain_overflow_dont, /* Complain on overflow. */
260 bfd_elf_generic_reloc, /* Special Function. */
261 "R_MICROBLAZE_GOTPC_64", /* Name. */
262 false, /* Partial Inplace. */
263 0, /* Source Mask. */
264 0x0000ffff, /* Dest Mask. */
265 true), /* PC relative offset? */
267 /* A 64 bit TEXTPCREL relocation. Table-entry not really used. */
268 HOWTO (R_MICROBLAZE_TEXTPCREL_64, /* Type. */
269 0, /* Rightshift. */
270 4, /* Size. */
271 16, /* Bitsize. */
272 true, /* PC_relative. */
273 0, /* Bitpos. */
274 complain_overflow_dont, /* Complain on overflow. */
275 bfd_elf_generic_reloc, /* Special Function. */
276 "R_MICROBLAZE_TEXTPCREL_64", /* Name. */
277 false, /* Partial Inplace. */
278 0, /* Source Mask. */
279 0x0000ffff, /* Dest Mask. */
280 true), /* PC relative offset? */
282 /* A 64 bit GOT relocation. Table-entry not really used. */
283 HOWTO (R_MICROBLAZE_GOT_64, /* Type. */
284 0, /* Rightshift. */
285 4, /* Size. */
286 16, /* Bitsize. */
287 false, /* PC_relative. */
288 0, /* Bitpos. */
289 complain_overflow_dont, /* Complain on overflow. */
290 bfd_elf_generic_reloc,/* Special Function. */
291 "R_MICROBLAZE_GOT_64",/* Name. */
292 false, /* Partial Inplace. */
293 0, /* Source Mask. */
294 0x0000ffff, /* Dest Mask. */
295 false), /* PC relative offset? */
297 /* A 64 bit TEXTREL relocation. Table-entry not really used. */
298 HOWTO (R_MICROBLAZE_TEXTREL_64, /* Type. */
299 0, /* Rightshift. */
300 4, /* Size. */
301 16, /* Bitsize. */
302 false, /* PC_relative. */
303 0, /* Bitpos. */
304 complain_overflow_dont, /* Complain on overflow. */
305 bfd_elf_generic_reloc,/* Special Function. */
306 "R_MICROBLAZE_TEXTREL_64",/* Name. */
307 false, /* Partial Inplace. */
308 0, /* Source Mask. */
309 0x0000ffff, /* Dest Mask. */
310 false), /* PC relative offset? */
312 /* A 64 bit PLT relocation. Table-entry not really used. */
313 HOWTO (R_MICROBLAZE_PLT_64, /* Type. */
314 0, /* Rightshift. */
315 4, /* Size. */
316 16, /* Bitsize. */
317 true, /* PC_relative. */
318 0, /* Bitpos. */
319 complain_overflow_dont, /* Complain on overflow. */
320 bfd_elf_generic_reloc,/* Special Function. */
321 "R_MICROBLAZE_PLT_64",/* Name. */
322 false, /* Partial Inplace. */
323 0, /* Source Mask. */
324 0x0000ffff, /* Dest Mask. */
325 true), /* PC relative offset? */
327 /* Table-entry not really used. */
328 HOWTO (R_MICROBLAZE_REL, /* Type. */
329 0, /* Rightshift. */
330 4, /* Size. */
331 16, /* Bitsize. */
332 true, /* PC_relative. */
333 0, /* Bitpos. */
334 complain_overflow_dont, /* Complain on overflow. */
335 bfd_elf_generic_reloc,/* Special Function. */
336 "R_MICROBLAZE_REL", /* Name. */
337 false, /* Partial Inplace. */
338 0, /* Source Mask. */
339 0x0000ffff, /* Dest Mask. */
340 true), /* PC relative offset? */
342 /* Table-entry not really used. */
343 HOWTO (R_MICROBLAZE_JUMP_SLOT,/* Type. */
344 0, /* Rightshift. */
345 4, /* Size. */
346 16, /* Bitsize. */
347 true, /* PC_relative. */
348 0, /* Bitpos. */
349 complain_overflow_dont, /* Complain on overflow. */
350 bfd_elf_generic_reloc,/* Special Function. */
351 "R_MICROBLAZE_JUMP_SLOT", /* Name. */
352 false, /* Partial Inplace. */
353 0, /* Source Mask. */
354 0x0000ffff, /* Dest Mask. */
355 true), /* PC relative offset? */
357 /* Table-entry not really used. */
358 HOWTO (R_MICROBLAZE_GLOB_DAT,/* Type. */
359 0, /* Rightshift. */
360 4, /* Size. */
361 16, /* Bitsize. */
362 true, /* PC_relative. */
363 0, /* Bitpos. */
364 complain_overflow_dont, /* Complain on overflow. */
365 bfd_elf_generic_reloc,/* Special Function. */
366 "R_MICROBLAZE_GLOB_DAT", /* Name. */
367 false, /* Partial Inplace. */
368 0, /* Source Mask. */
369 0x0000ffff, /* Dest Mask. */
370 true), /* PC relative offset? */
372 /* A 64 bit GOT relative relocation. Table-entry not really used. */
373 HOWTO (R_MICROBLAZE_GOTOFF_64, /* Type. */
374 0, /* Rightshift. */
375 4, /* Size. */
376 16, /* Bitsize. */
377 false, /* PC_relative. */
378 0, /* Bitpos. */
379 complain_overflow_dont, /* Complain on overflow. */
380 bfd_elf_generic_reloc,/* Special Function. */
381 "R_MICROBLAZE_GOTOFF_64", /* Name. */
382 false, /* Partial Inplace. */
383 0, /* Source Mask. */
384 0x0000ffff, /* Dest Mask. */
385 false), /* PC relative offset? */
387 /* A 32 bit GOT relative relocation. Table-entry not really used. */
388 HOWTO (R_MICROBLAZE_GOTOFF_32, /* Type. */
389 0, /* Rightshift. */
390 4, /* Size. */
391 16, /* Bitsize. */
392 false, /* PC_relative. */
393 0, /* Bitpos. */
394 complain_overflow_dont, /* Complain on overflow. */
395 bfd_elf_generic_reloc, /* Special Function. */
396 "R_MICROBLAZE_GOTOFF_32", /* Name. */
397 false, /* Partial Inplace. */
398 0, /* Source Mask. */
399 0x0000ffff, /* Dest Mask. */
400 false), /* PC relative offset? */
402 /* COPY relocation. Table-entry not really used. */
403 HOWTO (R_MICROBLAZE_COPY, /* Type. */
404 0, /* Rightshift. */
405 4, /* Size. */
406 16, /* Bitsize. */
407 false, /* PC_relative. */
408 0, /* Bitpos. */
409 complain_overflow_dont, /* Complain on overflow. */
410 bfd_elf_generic_reloc,/* Special Function. */
411 "R_MICROBLAZE_COPY", /* Name. */
412 false, /* Partial Inplace. */
413 0, /* Source Mask. */
414 0x0000ffff, /* Dest Mask. */
415 false), /* PC relative offset? */
417 /* Marker relocs for TLS. */
418 HOWTO (R_MICROBLAZE_TLS,
419 0, /* rightshift */
420 4, /* size */
421 32, /* bitsize */
422 false, /* pc_relative */
423 0, /* bitpos */
424 complain_overflow_dont, /* complain_on_overflow */
425 bfd_elf_generic_reloc, /* special_function */
426 "R_MICROBLAZE_TLS", /* name */
427 false, /* partial_inplace */
428 0, /* src_mask */
429 0x0000ffff, /* dst_mask */
430 false), /* pcrel_offset */
432 HOWTO (R_MICROBLAZE_TLSGD,
433 0, /* rightshift */
434 4, /* size */
435 32, /* bitsize */
436 false, /* pc_relative */
437 0, /* bitpos */
438 complain_overflow_dont, /* complain_on_overflow */
439 bfd_elf_generic_reloc, /* special_function */
440 "R_MICROBLAZE_TLSGD", /* name */
441 false, /* partial_inplace */
442 0, /* src_mask */
443 0x0000ffff, /* dst_mask */
444 false), /* pcrel_offset */
446 HOWTO (R_MICROBLAZE_TLSLD,
447 0, /* rightshift */
448 4, /* size */
449 32, /* bitsize */
450 false, /* pc_relative */
451 0, /* bitpos */
452 complain_overflow_dont, /* complain_on_overflow */
453 bfd_elf_generic_reloc, /* special_function */
454 "R_MICROBLAZE_TLSLD", /* name */
455 false, /* partial_inplace */
456 0, /* src_mask */
457 0x0000ffff, /* dst_mask */
458 false), /* pcrel_offset */
460 /* Computes the load module index of the load module that contains the
461 definition of its TLS sym. */
462 HOWTO (R_MICROBLAZE_TLSDTPMOD32,
463 0, /* rightshift */
464 4, /* size */
465 32, /* bitsize */
466 false, /* pc_relative */
467 0, /* bitpos */
468 complain_overflow_dont, /* complain_on_overflow */
469 bfd_elf_generic_reloc, /* special_function */
470 "R_MICROBLAZE_TLSDTPMOD32", /* name */
471 false, /* partial_inplace */
472 0, /* src_mask */
473 0x0000ffff, /* dst_mask */
474 false), /* pcrel_offset */
476 /* Computes a dtv-relative displacement, the difference between the value
477 of sym+add and the base address of the thread-local storage block that
478 contains the definition of sym, minus 0x8000. Used for initializing GOT */
479 HOWTO (R_MICROBLAZE_TLSDTPREL32,
480 0, /* rightshift */
481 4, /* size */
482 32, /* bitsize */
483 false, /* pc_relative */
484 0, /* bitpos */
485 complain_overflow_dont, /* complain_on_overflow */
486 bfd_elf_generic_reloc, /* special_function */
487 "R_MICROBLAZE_TLSDTPREL32", /* name */
488 false, /* partial_inplace */
489 0, /* src_mask */
490 0x0000ffff, /* dst_mask */
491 false), /* pcrel_offset */
493 /* Computes a dtv-relative displacement, the difference between the value
494 of sym+add and the base address of the thread-local storage block that
495 contains the definition of sym, minus 0x8000. */
496 HOWTO (R_MICROBLAZE_TLSDTPREL64,
497 0, /* rightshift */
498 4, /* size */
499 32, /* bitsize */
500 false, /* pc_relative */
501 0, /* bitpos */
502 complain_overflow_dont, /* complain_on_overflow */
503 bfd_elf_generic_reloc, /* special_function */
504 "R_MICROBLAZE_TLSDTPREL64", /* name */
505 false, /* partial_inplace */
506 0, /* src_mask */
507 0x0000ffff, /* dst_mask */
508 false), /* pcrel_offset */
510 /* Computes a tp-relative displacement, the difference between the value of
511 sym+add and the value of the thread pointer (r13). */
512 HOWTO (R_MICROBLAZE_TLSGOTTPREL32,
513 0, /* rightshift */
514 4, /* size */
515 32, /* bitsize */
516 false, /* pc_relative */
517 0, /* bitpos */
518 complain_overflow_dont, /* complain_on_overflow */
519 bfd_elf_generic_reloc, /* special_function */
520 "R_MICROBLAZE_TLSGOTTPREL32", /* name */
521 false, /* partial_inplace */
522 0, /* src_mask */
523 0x0000ffff, /* dst_mask */
524 false), /* pcrel_offset */
526 /* Computes a tp-relative displacement, the difference between the value of
527 sym+add and the value of the thread pointer (r13). */
528 HOWTO (R_MICROBLAZE_TLSTPREL32,
529 0, /* rightshift */
530 4, /* size */
531 32, /* bitsize */
532 false, /* pc_relative */
533 0, /* bitpos */
534 complain_overflow_dont, /* complain_on_overflow */
535 bfd_elf_generic_reloc, /* special_function */
536 "R_MICROBLAZE_TLSTPREL32", /* name */
537 false, /* partial_inplace */
538 0, /* src_mask */
539 0x0000ffff, /* dst_mask */
540 false), /* pcrel_offset */
544 #ifndef NUM_ELEM
545 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
546 #endif
548 /* Initialize the microblaze_elf_howto_table, so that linear accesses can be done. */
550 static void
551 microblaze_elf_howto_init (void)
553 unsigned int i;
555 for (i = NUM_ELEM (microblaze_elf_howto_raw); i--;)
557 unsigned int type;
559 type = microblaze_elf_howto_raw[i].type;
561 BFD_ASSERT (type < NUM_ELEM (microblaze_elf_howto_table));
563 microblaze_elf_howto_table [type] = & microblaze_elf_howto_raw [i];
567 static reloc_howto_type *
568 microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
569 bfd_reloc_code_real_type code)
571 enum elf_microblaze_reloc_type microblaze_reloc = R_MICROBLAZE_NONE;
573 switch (code)
575 case BFD_RELOC_NONE:
576 microblaze_reloc = R_MICROBLAZE_NONE;
577 break;
578 case BFD_RELOC_MICROBLAZE_32_NONE:
579 microblaze_reloc = R_MICROBLAZE_32_NONE;
580 break;
581 case BFD_RELOC_MICROBLAZE_64_NONE:
582 microblaze_reloc = R_MICROBLAZE_64_NONE;
583 break;
584 case BFD_RELOC_32:
585 microblaze_reloc = R_MICROBLAZE_32;
586 break;
587 /* RVA is treated the same as 32 */
588 case BFD_RELOC_RVA:
589 microblaze_reloc = R_MICROBLAZE_32;
590 break;
591 case BFD_RELOC_32_PCREL:
592 microblaze_reloc = R_MICROBLAZE_32_PCREL;
593 break;
594 case BFD_RELOC_64_PCREL:
595 microblaze_reloc = R_MICROBLAZE_64_PCREL;
596 break;
597 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
598 microblaze_reloc = R_MICROBLAZE_32_PCREL_LO;
599 break;
600 case BFD_RELOC_64:
601 microblaze_reloc = R_MICROBLAZE_64;
602 break;
603 case BFD_RELOC_MICROBLAZE_32_LO:
604 microblaze_reloc = R_MICROBLAZE_32_LO;
605 break;
606 case BFD_RELOC_MICROBLAZE_32_ROSDA:
607 microblaze_reloc = R_MICROBLAZE_SRO32;
608 break;
609 case BFD_RELOC_MICROBLAZE_32_RWSDA:
610 microblaze_reloc = R_MICROBLAZE_SRW32;
611 break;
612 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
613 microblaze_reloc = R_MICROBLAZE_32_SYM_OP_SYM;
614 break;
615 case BFD_RELOC_VTABLE_INHERIT:
616 microblaze_reloc = R_MICROBLAZE_GNU_VTINHERIT;
617 break;
618 case BFD_RELOC_VTABLE_ENTRY:
619 microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
620 break;
621 case BFD_RELOC_MICROBLAZE_64_GOTPC:
622 microblaze_reloc = R_MICROBLAZE_GOTPC_64;
623 break;
624 case BFD_RELOC_MICROBLAZE_64_GOT:
625 microblaze_reloc = R_MICROBLAZE_GOT_64;
626 break;
627 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
628 microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64;
629 break;
630 case BFD_RELOC_MICROBLAZE_64_TEXTREL:
631 microblaze_reloc = R_MICROBLAZE_TEXTREL_64;
632 break;
633 case BFD_RELOC_MICROBLAZE_64_PLT:
634 microblaze_reloc = R_MICROBLAZE_PLT_64;
635 break;
636 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
637 microblaze_reloc = R_MICROBLAZE_GOTOFF_64;
638 break;
639 case BFD_RELOC_MICROBLAZE_32_GOTOFF:
640 microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
641 break;
642 case BFD_RELOC_MICROBLAZE_64_TLSGD:
643 microblaze_reloc = R_MICROBLAZE_TLSGD;
644 break;
645 case BFD_RELOC_MICROBLAZE_64_TLSLD:
646 microblaze_reloc = R_MICROBLAZE_TLSLD;
647 break;
648 case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
649 microblaze_reloc = R_MICROBLAZE_TLSDTPREL32;
650 break;
651 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
652 microblaze_reloc = R_MICROBLAZE_TLSDTPREL64;
653 break;
654 case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
655 microblaze_reloc = R_MICROBLAZE_TLSDTPMOD32;
656 break;
657 case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
658 microblaze_reloc = R_MICROBLAZE_TLSGOTTPREL32;
659 break;
660 case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
661 microblaze_reloc = R_MICROBLAZE_TLSTPREL32;
662 break;
663 case BFD_RELOC_MICROBLAZE_COPY:
664 microblaze_reloc = R_MICROBLAZE_COPY;
665 break;
666 default:
667 return (reloc_howto_type *) NULL;
670 if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
671 /* Initialize howto table if needed. */
672 microblaze_elf_howto_init ();
674 return microblaze_elf_howto_table [(int) microblaze_reloc];
677 static reloc_howto_type *
678 microblaze_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
679 const char *r_name)
681 unsigned int i;
683 for (i = 0; i < NUM_ELEM (microblaze_elf_howto_raw); i++)
684 if (microblaze_elf_howto_raw[i].name != NULL
685 && strcasecmp (microblaze_elf_howto_raw[i].name, r_name) == 0)
686 return &microblaze_elf_howto_raw[i];
688 return NULL;
691 /* Set the howto pointer for a RCE ELF reloc. */
693 static bool
694 microblaze_elf_info_to_howto (bfd * abfd,
695 arelent * cache_ptr,
696 Elf_Internal_Rela * dst)
698 unsigned int r_type;
700 if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
701 /* Initialize howto table if needed. */
702 microblaze_elf_howto_init ();
704 r_type = ELF32_R_TYPE (dst->r_info);
705 if (r_type >= R_MICROBLAZE_max)
707 /* xgettext:c-format */
708 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
709 abfd, r_type);
710 bfd_set_error (bfd_error_bad_value);
711 return false;
714 cache_ptr->howto = microblaze_elf_howto_table [r_type];
715 return true;
718 /* Relax table contains information about instructions which can
719 be removed by relaxation -- replacing a long address with a
720 short address. */
721 struct relax_table
723 /* Address where bytes may be deleted. */
724 bfd_vma addr;
726 /* Number of bytes to be deleted. */
727 size_t size;
730 struct _microblaze_elf_section_data
732 struct bfd_elf_section_data elf;
733 /* Count of used relaxation table entries. */
734 size_t relax_count;
735 /* Relaxation table. */
736 struct relax_table *relax;
739 #define microblaze_elf_section_data(sec) \
740 ((struct _microblaze_elf_section_data *) elf_section_data (sec))
742 static bool
743 microblaze_elf_new_section_hook (bfd *abfd, asection *sec)
745 if (!sec->used_by_bfd)
747 struct _microblaze_elf_section_data *sdata;
748 size_t amt = sizeof (*sdata);
750 sdata = bfd_zalloc (abfd, amt);
751 if (sdata == NULL)
752 return false;
753 sec->used_by_bfd = sdata;
756 return _bfd_elf_new_section_hook (abfd, sec);
759 /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'. */
761 static bool
762 microblaze_elf_is_local_label_name (bfd *abfd, const char *name)
764 if (name[0] == 'L' && name[1] == '.')
765 return true;
767 if (name[0] == '$' && name[1] == 'L')
768 return true;
770 /* With gcc, the labels go back to starting with '.', so we accept
771 the generic ELF local label syntax as well. */
772 return _bfd_elf_is_local_label_name (abfd, name);
775 /* ELF linker hash entry. */
777 struct elf32_mb_link_hash_entry
779 struct elf_link_hash_entry elf;
781 /* TLS Reference Types for the symbol; Updated by check_relocs */
782 #define TLS_GD 1 /* GD reloc. */
783 #define TLS_LD 2 /* LD reloc. */
784 #define TLS_TPREL 4 /* TPREL reloc, => IE. */
785 #define TLS_DTPREL 8 /* DTPREL reloc, => LD. */
786 #define TLS_TLS 16 /* Any TLS reloc. */
787 unsigned char tls_mask;
791 #define IS_TLS_GD(x) (x == (TLS_TLS | TLS_GD))
792 #define IS_TLS_LD(x) (x == (TLS_TLS | TLS_LD))
793 #define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
794 #define IS_TLS_NONE(x) (x == 0)
796 #define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
798 /* ELF linker hash table. */
800 struct elf32_mb_link_hash_table
802 struct elf_link_hash_table elf;
804 /* TLS Local Dynamic GOT Entry */
805 union {
806 bfd_signed_vma refcount;
807 bfd_vma offset;
808 } tlsld_got;
811 /* Nonzero if this section has TLS related relocations. */
812 #define has_tls_reloc sec_flg0
814 /* Get the ELF linker hash table from a link_info structure. */
816 #define elf32_mb_hash_table(p) \
817 ((is_elf_hash_table ((p)->hash) \
818 && elf_hash_table_id (elf_hash_table (p)) == MICROBLAZE_ELF_DATA) \
819 ? (struct elf32_mb_link_hash_table *) (p)->hash : NULL)
821 /* Create an entry in a microblaze ELF linker hash table. */
823 static struct bfd_hash_entry *
824 link_hash_newfunc (struct bfd_hash_entry *entry,
825 struct bfd_hash_table *table,
826 const char *string)
828 /* Allocate the structure if it has not already been allocated by a
829 subclass. */
830 if (entry == NULL)
832 entry = bfd_hash_allocate (table,
833 sizeof (struct elf32_mb_link_hash_entry));
834 if (entry == NULL)
835 return entry;
838 /* Call the allocation method of the superclass. */
839 entry = _bfd_elf_link_hash_newfunc (entry, table, string);
840 if (entry != NULL)
842 struct elf32_mb_link_hash_entry *eh;
844 eh = (struct elf32_mb_link_hash_entry *) entry;
845 eh->tls_mask = 0;
848 return entry;
851 /* Create a mb ELF linker hash table. */
853 static struct bfd_link_hash_table *
854 microblaze_elf_link_hash_table_create (bfd *abfd)
856 struct elf32_mb_link_hash_table *ret;
857 size_t amt = sizeof (struct elf32_mb_link_hash_table);
859 ret = (struct elf32_mb_link_hash_table *) bfd_zmalloc (amt);
860 if (ret == NULL)
861 return NULL;
863 if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
864 sizeof (struct elf32_mb_link_hash_entry),
865 MICROBLAZE_ELF_DATA))
867 free (ret);
868 return NULL;
871 return &ret->elf.root;
874 /* Set the values of the small data pointers. */
876 static void
877 microblaze_elf_final_sdp (struct bfd_link_info *info)
879 struct bfd_link_hash_entry *h;
881 h = bfd_link_hash_lookup (info->hash, RO_SDA_ANCHOR_NAME, false, false, true);
882 if (h != (struct bfd_link_hash_entry *) NULL
883 && h->type == bfd_link_hash_defined)
884 ro_small_data_pointer = (h->u.def.value
885 + h->u.def.section->output_section->vma
886 + h->u.def.section->output_offset);
888 h = bfd_link_hash_lookup (info->hash, RW_SDA_ANCHOR_NAME, false, false, true);
889 if (h != (struct bfd_link_hash_entry *) NULL
890 && h->type == bfd_link_hash_defined)
891 rw_small_data_pointer = (h->u.def.value
892 + h->u.def.section->output_section->vma
893 + h->u.def.section->output_offset);
896 static bfd_vma
897 dtprel_base (struct bfd_link_info *info)
899 /* If tls_sec is NULL, we should have signalled an error already. */
900 if (elf_hash_table (info)->tls_sec == NULL)
901 return 0;
902 return elf_hash_table (info)->tls_sec->vma;
905 /* The size of the thread control block. */
906 #define TCB_SIZE 8
908 /* Output a simple dynamic relocation into SRELOC. */
910 static void
911 microblaze_elf_output_dynamic_relocation (bfd *output_bfd,
912 asection *sreloc,
913 unsigned long reloc_index,
914 unsigned long indx,
915 int r_type,
916 bfd_vma offset,
917 bfd_vma addend)
920 Elf_Internal_Rela rel;
922 rel.r_info = ELF32_R_INFO (indx, r_type);
923 rel.r_offset = offset;
924 rel.r_addend = addend;
926 bfd_elf32_swap_reloca_out (output_bfd, &rel,
927 (sreloc->contents + reloc_index * sizeof (Elf32_External_Rela)));
930 /* This code is taken from elf32-m32r.c
931 There is some attempt to make this function usable for many architectures,
932 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
933 if only to serve as a learning tool.
935 The RELOCATE_SECTION function is called by the new ELF backend linker
936 to handle the relocations for a section.
938 The relocs are always passed as Rela structures; if the section
939 actually uses Rel structures, the r_addend field will always be
940 zero.
942 This function is responsible for adjust the section contents as
943 necessary, and (if using Rela relocs and generating a
944 relocatable output file) adjusting the reloc addend as
945 necessary.
947 This function does not have to worry about setting the reloc
948 address or the reloc symbol index.
950 LOCAL_SYMS is a pointer to the swapped in local symbols.
952 LOCAL_SECTIONS is an array giving the section in the input file
953 corresponding to the st_shndx field of each local symbol.
955 The global hash table entry for the global symbols can be found
956 via elf_sym_hashes (input_bfd).
958 When generating relocatable output, this function must handle
959 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
960 going to be the section symbol corresponding to the output
961 section, which means that the addend must be adjusted
962 accordingly. */
964 static int
965 microblaze_elf_relocate_section (bfd *output_bfd,
966 struct bfd_link_info *info,
967 bfd *input_bfd,
968 asection *input_section,
969 bfd_byte *contents,
970 Elf_Internal_Rela *relocs,
971 Elf_Internal_Sym *local_syms,
972 asection **local_sections)
974 struct elf32_mb_link_hash_table *htab;
975 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
976 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
977 Elf_Internal_Rela *rel, *relend;
978 int endian = (bfd_little_endian (output_bfd)) ? 0 : 2;
979 /* Assume success. */
980 bool ret = true;
981 asection *sreloc;
982 bfd_vma *local_got_offsets;
983 unsigned int tls_type;
985 if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
986 microblaze_elf_howto_init ();
988 htab = elf32_mb_hash_table (info);
989 if (htab == NULL)
990 return false;
992 local_got_offsets = elf_local_got_offsets (input_bfd);
994 sreloc = elf_section_data (input_section)->sreloc;
996 rel = relocs;
997 relend = relocs + input_section->reloc_count;
998 for (; rel < relend; rel++)
1000 int r_type;
1001 reloc_howto_type *howto;
1002 unsigned long r_symndx;
1003 bfd_vma addend = rel->r_addend;
1004 bfd_vma offset = rel->r_offset;
1005 struct elf_link_hash_entry *h;
1006 Elf_Internal_Sym *sym;
1007 asection *sec;
1008 const char *sym_name;
1009 bfd_reloc_status_type r = bfd_reloc_ok;
1010 const char *errmsg = NULL;
1011 bool unresolved_reloc = false;
1013 h = NULL;
1014 r_type = ELF32_R_TYPE (rel->r_info);
1015 tls_type = 0;
1017 if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
1019 /* xgettext:c-format */
1020 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
1021 input_bfd, (int) r_type);
1022 bfd_set_error (bfd_error_bad_value);
1023 ret = false;
1024 continue;
1027 howto = microblaze_elf_howto_table[r_type];
1028 r_symndx = ELF32_R_SYM (rel->r_info);
1030 if (bfd_link_relocatable (info))
1032 /* This is a relocatable link. We don't have to change
1033 anything, unless the reloc is against a section symbol,
1034 in which case we have to adjust according to where the
1035 section symbol winds up in the output section. */
1036 sec = NULL;
1037 if (r_symndx >= symtab_hdr->sh_info)
1038 /* External symbol. */
1039 continue;
1041 /* Local symbol. */
1042 sym = local_syms + r_symndx;
1043 sym_name = "<local symbol>";
1044 /* STT_SECTION: symbol is associated with a section. */
1045 if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
1046 /* Symbol isn't associated with a section. Nothing to do. */
1047 continue;
1049 sec = local_sections[r_symndx];
1050 addend += sec->output_offset + sym->st_value;
1051 #ifndef USE_REL
1052 /* This can't be done for USE_REL because it doesn't mean anything
1053 and elf_link_input_bfd asserts this stays zero. */
1054 /* rel->r_addend = addend; */
1055 #endif
1057 #ifndef USE_REL
1058 /* Addends are stored with relocs. We're done. */
1059 continue;
1060 #else /* USE_REL */
1061 /* If partial_inplace, we need to store any additional addend
1062 back in the section. */
1063 if (!howto->partial_inplace)
1064 continue;
1065 /* ??? Here is a nice place to call a special_function like handler. */
1066 r = _bfd_relocate_contents (howto, input_bfd, addend,
1067 contents + offset);
1068 #endif /* USE_REL */
1070 else
1072 bfd_vma relocation;
1073 bool resolved_to_zero;
1075 /* This is a final link. */
1076 sym = NULL;
1077 sec = NULL;
1078 unresolved_reloc = false;
1080 if (r_symndx < symtab_hdr->sh_info)
1082 /* Local symbol. */
1083 sym = local_syms + r_symndx;
1084 sec = local_sections[r_symndx];
1085 if (sec == 0)
1086 continue;
1087 sym_name = "<local symbol>";
1088 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1089 /* r_addend may have changed if the reference section was
1090 a merge section. */
1091 addend = rel->r_addend;
1093 else
1095 /* External symbol. */
1096 bool warned ATTRIBUTE_UNUSED;
1097 bool ignored ATTRIBUTE_UNUSED;
1099 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1100 r_symndx, symtab_hdr, sym_hashes,
1101 h, sec, relocation,
1102 unresolved_reloc, warned, ignored);
1103 sym_name = h->root.root.string;
1106 /* Sanity check the address. */
1107 if (offset > bfd_get_section_limit (input_bfd, input_section))
1109 r = bfd_reloc_outofrange;
1110 goto check_reloc;
1113 resolved_to_zero = (h != NULL
1114 && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
1116 switch ((int) r_type)
1118 case (int) R_MICROBLAZE_SRO32 :
1120 const char *name;
1122 /* Only relocate if the symbol is defined. */
1123 if (sec)
1125 name = bfd_section_name (sec);
1127 if (strcmp (name, ".sdata2") == 0
1128 || strcmp (name, ".sbss2") == 0)
1130 if (ro_small_data_pointer == 0)
1131 microblaze_elf_final_sdp (info);
1132 if (ro_small_data_pointer == 0)
1134 ret = false;
1135 r = bfd_reloc_undefined;
1136 goto check_reloc;
1139 /* At this point `relocation' contains the object's
1140 address. */
1141 relocation -= ro_small_data_pointer;
1142 /* Now it contains the offset from _SDA2_BASE_. */
1143 r = _bfd_final_link_relocate (howto, input_bfd,
1144 input_section,
1145 contents, offset,
1146 relocation, addend);
1148 else
1150 _bfd_error_handler
1151 /* xgettext:c-format */
1152 (_("%pB: the target (%s) of an %s relocation"
1153 " is in the wrong section (%pA)"),
1154 input_bfd,
1155 sym_name,
1156 microblaze_elf_howto_table[(int) r_type]->name,
1157 sec);
1158 /*bfd_set_error (bfd_error_bad_value); ??? why? */
1159 ret = false;
1160 continue;
1164 break;
1166 case (int) R_MICROBLAZE_SRW32 :
1168 const char *name;
1170 /* Only relocate if the symbol is defined. */
1171 if (sec)
1173 name = bfd_section_name (sec);
1175 if (strcmp (name, ".sdata") == 0
1176 || strcmp (name, ".sbss") == 0)
1178 if (rw_small_data_pointer == 0)
1179 microblaze_elf_final_sdp (info);
1180 if (rw_small_data_pointer == 0)
1182 ret = false;
1183 r = bfd_reloc_undefined;
1184 goto check_reloc;
1187 /* At this point `relocation' contains the object's
1188 address. */
1189 relocation -= rw_small_data_pointer;
1190 /* Now it contains the offset from _SDA_BASE_. */
1191 r = _bfd_final_link_relocate (howto, input_bfd,
1192 input_section,
1193 contents, offset,
1194 relocation, addend);
1196 else
1198 _bfd_error_handler
1199 /* xgettext:c-format */
1200 (_("%pB: the target (%s) of an %s relocation"
1201 " is in the wrong section (%pA)"),
1202 input_bfd,
1203 sym_name,
1204 microblaze_elf_howto_table[(int) r_type]->name,
1205 sec);
1206 /*bfd_set_error (bfd_error_bad_value); ??? why? */
1207 ret = false;
1208 continue;
1212 break;
1214 case (int) R_MICROBLAZE_32_SYM_OP_SYM:
1215 break; /* Do nothing. */
1217 case (int) R_MICROBLAZE_GOTPC_64:
1218 relocation = (htab->elf.sgotplt->output_section->vma
1219 + htab->elf.sgotplt->output_offset);
1220 relocation -= (input_section->output_section->vma
1221 + input_section->output_offset
1222 + offset + INST_WORD_SIZE);
1223 relocation += addend;
1224 bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1225 contents + offset + endian);
1226 bfd_put_16 (input_bfd, relocation & 0xffff,
1227 contents + offset + endian + INST_WORD_SIZE);
1228 break;
1230 case (int) R_MICROBLAZE_TEXTPCREL_64:
1231 relocation = input_section->output_section->vma;
1232 relocation -= (input_section->output_section->vma
1233 + input_section->output_offset
1234 + offset + INST_WORD_SIZE);
1235 relocation += addend;
1236 bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1237 contents + offset + endian);
1238 bfd_put_16 (input_bfd, relocation & 0xffff,
1239 contents + offset + endian + INST_WORD_SIZE);
1240 break;
1242 case (int) R_MICROBLAZE_PLT_64:
1244 bfd_vma immediate;
1245 if (htab->elf.splt != NULL && h != NULL
1246 && h->plt.offset != (bfd_vma) -1)
1248 relocation = (htab->elf.splt->output_section->vma
1249 + htab->elf.splt->output_offset
1250 + h->plt.offset);
1251 unresolved_reloc = false;
1252 immediate = relocation - (input_section->output_section->vma
1253 + input_section->output_offset
1254 + offset + INST_WORD_SIZE);
1255 bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
1256 contents + offset + endian);
1257 bfd_put_16 (input_bfd, immediate & 0xffff,
1258 contents + offset + endian + INST_WORD_SIZE);
1260 else
1262 relocation -= (input_section->output_section->vma
1263 + input_section->output_offset
1264 + offset + INST_WORD_SIZE);
1265 immediate = relocation;
1266 bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
1267 contents + offset + endian);
1268 bfd_put_16 (input_bfd, immediate & 0xffff,
1269 contents + offset + endian + INST_WORD_SIZE);
1271 break;
1274 case (int) R_MICROBLAZE_TLSGD:
1275 tls_type = (TLS_TLS | TLS_GD);
1276 goto dogot;
1277 case (int) R_MICROBLAZE_TLSLD:
1278 tls_type = (TLS_TLS | TLS_LD);
1279 /* Fall through. */
1280 dogot:
1281 case (int) R_MICROBLAZE_GOT_64:
1283 bfd_vma *offp;
1284 bfd_vma off, off2;
1285 unsigned long indx;
1286 bfd_vma static_value;
1288 bool need_relocs = false;
1289 if (htab->elf.sgot == NULL)
1290 abort ();
1292 indx = 0;
1293 offp = NULL;
1295 /* 1. Identify GOT Offset;
1296 2. Compute Static Values
1297 3. Process Module Id, Process Offset
1298 4. Fixup Relocation with GOT offset value. */
1300 /* 1. Determine GOT Offset to use : TLS_LD, global, local */
1301 if (IS_TLS_LD (tls_type))
1302 offp = &htab->tlsld_got.offset;
1303 else if (h != NULL)
1305 if (htab->elf.sgotplt != NULL
1306 && h->got.offset != (bfd_vma) -1)
1307 offp = &h->got.offset;
1308 else
1309 abort ();
1311 else
1313 if (local_got_offsets == NULL)
1314 abort ();
1315 offp = &local_got_offsets[r_symndx];
1318 if (!offp)
1319 abort ();
1321 off = (*offp) & ~1;
1322 off2 = off;
1324 if (IS_TLS_LD(tls_type) || IS_TLS_GD(tls_type))
1325 off2 = off + 4;
1327 /* Symbol index to use for relocs */
1328 if (h != NULL)
1330 bool dyn =
1331 elf_hash_table (info)->dynamic_sections_created;
1333 if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
1334 bfd_link_pic (info),
1336 && (!bfd_link_pic (info)
1337 || !SYMBOL_REFERENCES_LOCAL (info, h)))
1338 indx = h->dynindx;
1341 /* Need to generate relocs ? */
1342 if ((bfd_link_pic (info) || indx != 0)
1343 && (h == NULL
1344 || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1345 && !resolved_to_zero)
1346 || h->root.type != bfd_link_hash_undefweak))
1347 need_relocs = true;
1349 /* 2. Compute/Emit Static value of r-expression */
1350 static_value = relocation + addend;
1352 /* 3. Process module-id and offset */
1353 if (! ((*offp) & 1) )
1355 bfd_vma got_offset;
1357 got_offset = (htab->elf.sgot->output_section->vma
1358 + htab->elf.sgot->output_offset
1359 + off);
1361 /* Process module-id */
1362 if (IS_TLS_LD(tls_type))
1364 if (! bfd_link_pic (info))
1365 bfd_put_32 (output_bfd, 1,
1366 htab->elf.sgot->contents + off);
1367 else
1368 microblaze_elf_output_dynamic_relocation
1369 (output_bfd,
1370 htab->elf.srelgot,
1371 htab->elf.srelgot->reloc_count++,
1372 /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32,
1373 got_offset, 0);
1375 else if (IS_TLS_GD(tls_type))
1377 if (! need_relocs)
1378 bfd_put_32 (output_bfd, 1,
1379 htab->elf.sgot->contents + off);
1380 else
1381 microblaze_elf_output_dynamic_relocation
1382 (output_bfd,
1383 htab->elf.srelgot,
1384 htab->elf.srelgot->reloc_count++,
1385 /* symindex= */ indx, R_MICROBLAZE_TLSDTPMOD32,
1386 got_offset, indx ? 0 : static_value);
1389 /* Process Offset */
1390 if (htab->elf.srelgot == NULL)
1391 abort ();
1393 got_offset = (htab->elf.sgot->output_section->vma
1394 + htab->elf.sgot->output_offset
1395 + off2);
1396 if (IS_TLS_LD(tls_type))
1398 /* For LD, offset should be 0 */
1399 *offp |= 1;
1400 bfd_put_32 (output_bfd, 0,
1401 htab->elf.sgot->contents + off2);
1403 else if (IS_TLS_GD(tls_type))
1405 *offp |= 1;
1406 static_value -= dtprel_base(info);
1407 if (need_relocs)
1408 microblaze_elf_output_dynamic_relocation
1409 (output_bfd,
1410 htab->elf.srelgot,
1411 htab->elf.srelgot->reloc_count++,
1412 /* symindex= */ indx, R_MICROBLAZE_TLSDTPREL32,
1413 got_offset, indx ? 0 : static_value);
1414 else
1415 bfd_put_32 (output_bfd, static_value,
1416 htab->elf.sgot->contents + off2);
1418 else
1420 bfd_put_32 (output_bfd, static_value,
1421 htab->elf.sgot->contents + off2);
1423 /* Relocs for dyn symbols generated by
1424 finish_dynamic_symbols */
1425 if (bfd_link_pic (info) && h == NULL)
1427 *offp |= 1;
1428 microblaze_elf_output_dynamic_relocation
1429 (output_bfd,
1430 htab->elf.srelgot,
1431 htab->elf.srelgot->reloc_count++,
1432 /* symindex= */ indx, R_MICROBLAZE_REL,
1433 got_offset, static_value);
1438 /* 4. Fixup Relocation with GOT offset value
1439 Compute relative address of GOT entry for applying
1440 the current relocation */
1441 relocation = htab->elf.sgot->output_section->vma
1442 + htab->elf.sgot->output_offset
1443 + off
1444 - htab->elf.sgotplt->output_section->vma
1445 - htab->elf.sgotplt->output_offset;
1447 /* Apply Current Relocation */
1448 bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1449 contents + offset + endian);
1450 bfd_put_16 (input_bfd, relocation & 0xffff,
1451 contents + offset + endian + INST_WORD_SIZE);
1453 unresolved_reloc = false;
1454 break;
1457 case (int) R_MICROBLAZE_GOTOFF_64:
1459 bfd_vma immediate;
1460 unsigned short lo, high;
1461 relocation += addend;
1462 relocation -= (htab->elf.sgotplt->output_section->vma
1463 + htab->elf.sgotplt->output_offset);
1464 /* Write this value into correct location. */
1465 immediate = relocation;
1466 lo = immediate & 0x0000ffff;
1467 high = (immediate >> 16) & 0x0000ffff;
1468 bfd_put_16 (input_bfd, high, contents + offset + endian);
1469 bfd_put_16 (input_bfd, lo,
1470 contents + offset + INST_WORD_SIZE + endian);
1471 break;
1474 case (int) R_MICROBLAZE_GOTOFF_32:
1476 relocation += addend;
1477 relocation -= (htab->elf.sgotplt->output_section->vma
1478 + htab->elf.sgotplt->output_offset);
1479 /* Write this value into correct location. */
1480 bfd_put_32 (input_bfd, relocation, contents + offset);
1481 break;
1484 case (int) R_MICROBLAZE_TLSDTPREL64:
1485 relocation += addend;
1486 relocation -= dtprel_base(info);
1487 bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1488 contents + offset + endian);
1489 bfd_put_16 (input_bfd, relocation & 0xffff,
1490 contents + offset + endian + INST_WORD_SIZE);
1491 break;
1492 case (int) R_MICROBLAZE_TEXTREL_64:
1493 case (int) R_MICROBLAZE_TEXTREL_32_LO:
1494 case (int) R_MICROBLAZE_64_PCREL :
1495 case (int) R_MICROBLAZE_64:
1496 case (int) R_MICROBLAZE_32:
1498 /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
1499 from removed linkonce sections, or sections discarded by
1500 a linker script. */
1501 if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
1503 relocation += addend;
1504 if (r_type == R_MICROBLAZE_32)
1505 bfd_put_32 (input_bfd, relocation, contents + offset);
1506 else
1508 if (r_type == R_MICROBLAZE_64_PCREL)
1509 relocation -= (input_section->output_section->vma
1510 + input_section->output_offset
1511 + offset + INST_WORD_SIZE);
1512 else if (r_type == R_MICROBLAZE_TEXTREL_64
1513 || r_type == R_MICROBLAZE_TEXTREL_32_LO)
1514 relocation -= input_section->output_section->vma;
1516 if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
1517 bfd_put_16 (input_bfd, relocation & 0xffff,
1518 contents + offset + endian);
1520 else
1522 bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1523 contents + offset + endian);
1524 bfd_put_16 (input_bfd, relocation & 0xffff,
1525 contents + offset + endian + INST_WORD_SIZE);
1528 break;
1531 if ((bfd_link_pic (info)
1532 && (h == NULL
1533 || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1534 && !resolved_to_zero)
1535 || h->root.type != bfd_link_hash_undefweak)
1536 && (!howto->pc_relative
1537 || (h != NULL
1538 && h->dynindx != -1
1539 && (!info->symbolic
1540 || !h->def_regular))))
1541 || (!bfd_link_pic (info)
1542 && h != NULL
1543 && h->dynindx != -1
1544 && !h->non_got_ref
1545 && ((h->def_dynamic
1546 && !h->def_regular)
1547 || h->root.type == bfd_link_hash_undefweak
1548 || h->root.type == bfd_link_hash_undefined)))
1550 Elf_Internal_Rela outrel;
1551 bfd_byte *loc;
1552 bool skip;
1554 /* When generating a shared object, these relocations
1555 are copied into the output file to be resolved at run
1556 time. */
1558 BFD_ASSERT (sreloc != NULL);
1560 skip = false;
1562 outrel.r_offset =
1563 _bfd_elf_section_offset (output_bfd, info, input_section,
1564 rel->r_offset);
1565 if (outrel.r_offset == (bfd_vma) -1)
1566 skip = true;
1567 else if (outrel.r_offset == (bfd_vma) -2)
1568 skip = true;
1569 outrel.r_offset += (input_section->output_section->vma
1570 + input_section->output_offset);
1572 if (skip)
1573 memset (&outrel, 0, sizeof outrel);
1574 /* h->dynindx may be -1 if the symbol was marked to
1575 become local. */
1576 else if (h != NULL
1577 && ((! info->symbolic && h->dynindx != -1)
1578 || !h->def_regular))
1580 BFD_ASSERT (h->dynindx != -1);
1581 outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
1582 outrel.r_addend = addend;
1584 else
1586 if (r_type == R_MICROBLAZE_32)
1588 outrel.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
1589 outrel.r_addend = relocation + addend;
1591 else
1593 BFD_FAIL ();
1594 _bfd_error_handler
1595 (_("%pB: probably compiled without -fPIC?"),
1596 input_bfd);
1597 bfd_set_error (bfd_error_bad_value);
1598 return false;
1602 loc = sreloc->contents;
1603 loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
1604 bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
1605 break;
1607 else
1609 relocation += addend;
1610 if (r_type == R_MICROBLAZE_32)
1611 bfd_put_32 (input_bfd, relocation, contents + offset);
1612 else
1614 if (r_type == R_MICROBLAZE_64_PCREL)
1615 relocation -= (input_section->output_section->vma
1616 + input_section->output_offset
1617 + offset + INST_WORD_SIZE);
1618 else if (r_type == R_MICROBLAZE_TEXTREL_64
1619 || r_type == R_MICROBLAZE_TEXTREL_32_LO)
1620 relocation -= input_section->output_section->vma;
1622 if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
1624 bfd_put_16 (input_bfd, relocation & 0xffff,
1625 contents + offset + endian);
1627 else
1629 bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1630 contents + offset + endian);
1631 bfd_put_16 (input_bfd, relocation & 0xffff,
1632 contents + offset + endian
1633 + INST_WORD_SIZE);
1636 break;
1640 default :
1641 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
1642 contents, offset,
1643 relocation, addend);
1644 break;
1648 check_reloc:
1650 if (r != bfd_reloc_ok)
1652 /* FIXME: This should be generic enough to go in a utility. */
1653 const char *name;
1655 if (h != NULL)
1656 name = h->root.root.string;
1657 else
1659 name = (bfd_elf_string_from_elf_section
1660 (input_bfd, symtab_hdr->sh_link, sym->st_name));
1661 if (name == NULL || *name == '\0')
1662 name = bfd_section_name (sec);
1665 if (errmsg != NULL)
1666 goto common_error;
1668 switch (r)
1670 case bfd_reloc_overflow:
1671 (*info->callbacks->reloc_overflow)
1672 (info, (h ? &h->root : NULL), name, howto->name,
1673 (bfd_vma) 0, input_bfd, input_section, offset);
1674 break;
1676 case bfd_reloc_undefined:
1677 (*info->callbacks->undefined_symbol)
1678 (info, name, input_bfd, input_section, offset, true);
1679 break;
1681 case bfd_reloc_outofrange:
1682 errmsg = _("internal error: out of range error");
1683 goto common_error;
1685 case bfd_reloc_notsupported:
1686 errmsg = _("internal error: unsupported relocation error");
1687 goto common_error;
1689 case bfd_reloc_dangerous:
1690 errmsg = _("internal error: dangerous error");
1691 goto common_error;
1693 default:
1694 errmsg = _("internal error: unknown error");
1695 /* Fall through. */
1696 common_error:
1697 (*info->callbacks->warning) (info, errmsg, name, input_bfd,
1698 input_section, offset);
1699 break;
1704 return ret;
1707 /* Calculate fixup value for reference. */
1709 static size_t
1710 calc_fixup (bfd_vma start, bfd_vma size, asection *sec)
1712 bfd_vma end = start + size;
1713 size_t i, fixup = 0;
1714 struct _microblaze_elf_section_data *sdata;
1716 if (sec == NULL || (sdata = microblaze_elf_section_data (sec)) == NULL)
1717 return 0;
1719 /* Look for addr in relax table, total fixup value. */
1720 for (i = 0; i < sdata->relax_count; i++)
1722 if (end <= sdata->relax[i].addr)
1723 break;
1724 if (end != start && start > sdata->relax[i].addr)
1725 continue;
1726 fixup += sdata->relax[i].size;
1728 return fixup;
1731 /* Read-modify-write into the bfd, an immediate value into appropriate fields of
1732 a 32-bit instruction. */
1733 static void
1734 microblaze_bfd_write_imm_value_32 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
1736 unsigned long instr = bfd_get_32 (abfd, bfd_addr);
1737 instr &= ~0x0000ffff;
1738 instr |= (val & 0x0000ffff);
1739 bfd_put_32 (abfd, instr, bfd_addr);
1742 /* Read-modify-write into the bfd, an immediate value into appropriate fields of
1743 two consecutive 32-bit instructions. */
1744 static void
1745 microblaze_bfd_write_imm_value_64 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
1747 unsigned long instr_hi;
1748 unsigned long instr_lo;
1750 instr_hi = bfd_get_32 (abfd, bfd_addr);
1751 instr_hi &= ~0x0000ffff;
1752 instr_hi |= ((val >> 16) & 0x0000ffff);
1753 bfd_put_32 (abfd, instr_hi, bfd_addr);
1755 instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
1756 instr_lo &= ~0x0000ffff;
1757 instr_lo |= (val & 0x0000ffff);
1758 bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
1761 static bool
1762 microblaze_elf_relax_section (bfd *abfd,
1763 asection *sec,
1764 struct bfd_link_info *link_info,
1765 bool *again)
1767 Elf_Internal_Shdr *symtab_hdr;
1768 Elf_Internal_Rela *internal_relocs;
1769 Elf_Internal_Rela *free_relocs = NULL;
1770 Elf_Internal_Rela *irel, *irelend;
1771 bfd_byte *contents = NULL;
1772 bfd_byte *free_contents = NULL;
1773 int rel_count;
1774 unsigned int shndx;
1775 size_t i, sym_index;
1776 asection *o;
1777 struct elf_link_hash_entry *sym_hash;
1778 Elf_Internal_Sym *isymbuf, *isymend;
1779 Elf_Internal_Sym *isym;
1780 size_t symcount;
1781 size_t offset;
1782 bfd_vma src, dest;
1783 struct _microblaze_elf_section_data *sdata;
1785 /* We only do this once per section. We may be able to delete some code
1786 by running multiple passes, but it is not worth it. */
1787 *again = false;
1789 /* Only do this for a text section. */
1790 if (bfd_link_relocatable (link_info)
1791 || (sec->flags & SEC_RELOC) == 0
1792 || (sec->flags & SEC_CODE) == 0
1793 || sec->reloc_count == 0
1794 || (sdata = microblaze_elf_section_data (sec)) == NULL)
1795 return true;
1797 BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
1799 /* If this is the first time we have been called for this section,
1800 initialize the cooked size. */
1801 if (sec->size == 0)
1802 sec->size = sec->rawsize;
1804 /* Get symbols for this section. */
1805 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1806 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1807 symcount = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
1808 if (isymbuf == NULL)
1809 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symcount,
1810 0, NULL, NULL, NULL);
1811 BFD_ASSERT (isymbuf != NULL);
1813 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
1814 if (internal_relocs == NULL)
1815 goto error_return;
1816 if (! link_info->keep_memory)
1817 free_relocs = internal_relocs;
1819 sdata->relax_count = 0;
1820 sdata->relax = (struct relax_table *) bfd_malloc ((sec->reloc_count + 1)
1821 * sizeof (*sdata->relax));
1822 if (sdata->relax == NULL)
1823 goto error_return;
1825 irelend = internal_relocs + sec->reloc_count;
1826 rel_count = 0;
1827 for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
1829 bfd_vma symval;
1830 if ((ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL)
1831 && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64)
1832 && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64))
1833 continue; /* Can't delete this reloc. */
1835 /* Get the section contents. */
1836 if (contents == NULL)
1838 if (elf_section_data (sec)->this_hdr.contents != NULL)
1839 contents = elf_section_data (sec)->this_hdr.contents;
1840 else
1842 contents = (bfd_byte *) bfd_malloc (sec->size);
1843 if (contents == NULL)
1844 goto error_return;
1845 free_contents = contents;
1847 if (!bfd_get_section_contents (abfd, sec, contents,
1848 (file_ptr) 0, sec->size))
1849 goto error_return;
1850 elf_section_data (sec)->this_hdr.contents = contents;
1854 /* Get the value of the symbol referred to by the reloc. */
1855 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1857 /* A local symbol. */
1858 asection *sym_sec;
1860 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1861 if (isym->st_shndx == SHN_UNDEF)
1862 sym_sec = bfd_und_section_ptr;
1863 else if (isym->st_shndx == SHN_ABS)
1864 sym_sec = bfd_abs_section_ptr;
1865 else if (isym->st_shndx == SHN_COMMON)
1866 sym_sec = bfd_com_section_ptr;
1867 else
1868 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1870 symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
1872 else
1874 unsigned long indx;
1875 struct elf_link_hash_entry *h;
1877 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1878 h = elf_sym_hashes (abfd)[indx];
1879 BFD_ASSERT (h != NULL);
1881 if (h->root.type != bfd_link_hash_defined
1882 && h->root.type != bfd_link_hash_defweak)
1883 /* This appears to be a reference to an undefined
1884 symbol. Just ignore it--it will be caught by the
1885 regular reloc processing. */
1886 continue;
1888 symval = (h->root.u.def.value
1889 + h->root.u.def.section->output_section->vma
1890 + h->root.u.def.section->output_offset);
1893 /* If this is a PC-relative reloc, subtract the instr offset from
1894 the symbol value. */
1895 if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_64_PCREL)
1897 symval = symval + irel->r_addend
1898 - (irel->r_offset
1899 + sec->output_section->vma
1900 + sec->output_offset);
1902 else if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64)
1904 symval = symval + irel->r_addend - (sec->output_section->vma);
1906 else
1907 symval += irel->r_addend;
1909 if ((symval & 0xffff8000) == 0
1910 || (symval & 0xffff8000) == 0xffff8000)
1912 /* We can delete this instruction. */
1913 sdata->relax[sdata->relax_count].addr = irel->r_offset;
1914 sdata->relax[sdata->relax_count].size = INST_WORD_SIZE;
1915 sdata->relax_count++;
1917 /* Rewrite relocation type. */
1918 switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
1920 case R_MICROBLAZE_64_PCREL:
1921 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1922 (int) R_MICROBLAZE_32_PCREL_LO);
1923 break;
1924 case R_MICROBLAZE_64:
1925 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1926 (int) R_MICROBLAZE_32_LO);
1927 break;
1928 case R_MICROBLAZE_TEXTREL_64:
1929 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1930 (int) R_MICROBLAZE_TEXTREL_32_LO);
1931 break;
1932 default:
1933 /* Cannot happen. */
1934 BFD_ASSERT (false);
1937 } /* Loop through all relocations. */
1939 /* Loop through the relocs again, and see if anything needs to change. */
1940 if (sdata->relax_count > 0)
1942 shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1943 rel_count = 0;
1944 sdata->relax[sdata->relax_count].addr = sec->size;
1946 for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
1948 bfd_vma nraddr;
1950 /* Get the new reloc address. */
1951 nraddr = irel->r_offset - calc_fixup (irel->r_offset, 0, sec);
1952 switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
1954 default:
1955 break;
1956 case R_MICROBLAZE_64_PCREL:
1957 break;
1958 case R_MICROBLAZE_TEXTREL_64:
1959 case R_MICROBLAZE_TEXTREL_32_LO:
1960 case R_MICROBLAZE_64:
1961 case R_MICROBLAZE_32_LO:
1962 /* If this reloc is against a symbol defined in this
1963 section, we must check the addend to see it will put the value in
1964 range to be adjusted, and hence must be changed. */
1965 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1967 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1968 /* Only handle relocs against .text. */
1969 if (isym->st_shndx == shndx
1970 && ELF32_ST_TYPE (isym->st_info) == STT_SECTION)
1971 irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
1973 break;
1974 case R_MICROBLAZE_NONE:
1975 case R_MICROBLAZE_32_NONE:
1977 /* This was a PC-relative instruction that was
1978 completely resolved. */
1979 size_t sfix, efix;
1980 bfd_vma target_address;
1981 target_address = irel->r_addend + irel->r_offset;
1982 sfix = calc_fixup (irel->r_offset, 0, sec);
1983 efix = calc_fixup (target_address, 0, sec);
1984 irel->r_addend -= (efix - sfix);
1985 /* Should use HOWTO. */
1986 microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
1987 irel->r_addend);
1989 break;
1990 case R_MICROBLAZE_64_NONE:
1992 /* This was a PC-relative 64-bit instruction that was
1993 completely resolved. */
1994 size_t sfix, efix;
1995 bfd_vma target_address;
1996 target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
1997 sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
1998 efix = calc_fixup (target_address, 0, sec);
1999 irel->r_addend -= (efix - sfix);
2000 microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset
2001 + INST_WORD_SIZE, irel->r_addend);
2003 break;
2005 irel->r_offset = nraddr;
2006 } /* Change all relocs in this section. */
2008 /* Look through all other sections. */
2009 for (o = abfd->sections; o != NULL; o = o->next)
2011 Elf_Internal_Rela *irelocs;
2012 Elf_Internal_Rela *irelscan, *irelscanend;
2013 bfd_byte *ocontents;
2015 if (o == sec
2016 || (o->flags & SEC_RELOC) == 0
2017 || o->reloc_count == 0)
2018 continue;
2020 /* We always cache the relocs. Perhaps, if info->keep_memory is
2021 FALSE, we should free them, if we are permitted to. */
2023 irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, true);
2024 if (irelocs == NULL)
2025 goto error_return;
2027 ocontents = NULL;
2028 irelscanend = irelocs + o->reloc_count;
2029 for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
2031 if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
2032 || (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_NONE))
2034 isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2036 /* Look at the reloc only if the value has been resolved. */
2037 if (isym->st_shndx == shndx
2038 && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2040 if (ocontents == NULL)
2042 if (elf_section_data (o)->this_hdr.contents != NULL)
2043 ocontents = elf_section_data (o)->this_hdr.contents;
2044 else
2046 /* We always cache the section contents.
2047 Perhaps, if info->keep_memory is FALSE, we
2048 should free them, if we are permitted to. */
2049 if (o->rawsize == 0)
2050 o->rawsize = o->size;
2051 ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2052 if (ocontents == NULL)
2053 goto error_return;
2054 if (!bfd_get_section_contents (abfd, o, ocontents,
2055 (file_ptr) 0,
2056 o->rawsize))
2057 goto error_return;
2058 elf_section_data (o)->this_hdr.contents = ocontents;
2062 irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
2064 else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_SYM_OP_SYM)
2066 isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2068 /* Look at the reloc only if the value has been resolved. */
2069 if (ocontents == NULL)
2071 if (elf_section_data (o)->this_hdr.contents != NULL)
2072 ocontents = elf_section_data (o)->this_hdr.contents;
2073 else
2075 /* We always cache the section contents.
2076 Perhaps, if info->keep_memory is FALSE, we
2077 should free them, if we are permitted to. */
2079 if (o->rawsize == 0)
2080 o->rawsize = o->size;
2081 ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2082 if (ocontents == NULL)
2083 goto error_return;
2084 if (!bfd_get_section_contents (abfd, o, ocontents,
2085 (file_ptr) 0,
2086 o->rawsize))
2087 goto error_return;
2088 elf_section_data (o)->this_hdr.contents = ocontents;
2091 irelscan->r_addend -= calc_fixup (irelscan->r_addend
2092 + isym->st_value,
2094 sec);
2097 else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO)
2098 || (ELF32_R_TYPE (irelscan->r_info)
2099 == (int) R_MICROBLAZE_32_LO)
2100 || (ELF32_R_TYPE (irelscan->r_info)
2101 == (int) R_MICROBLAZE_TEXTREL_32_LO))
2103 isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2105 /* Look at the reloc only if the value has been resolved. */
2106 if (isym->st_shndx == shndx
2107 && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2109 bfd_vma immediate;
2110 bfd_vma target_address;
2112 if (ocontents == NULL)
2114 if (elf_section_data (o)->this_hdr.contents != NULL)
2115 ocontents = elf_section_data (o)->this_hdr.contents;
2116 else
2118 /* We always cache the section contents.
2119 Perhaps, if info->keep_memory is FALSE, we
2120 should free them, if we are permitted to. */
2121 if (o->rawsize == 0)
2122 o->rawsize = o->size;
2123 ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2124 if (ocontents == NULL)
2125 goto error_return;
2126 if (!bfd_get_section_contents (abfd, o, ocontents,
2127 (file_ptr) 0,
2128 o->rawsize))
2129 goto error_return;
2130 elf_section_data (o)->this_hdr.contents = ocontents;
2134 unsigned long instr = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
2135 immediate = instr & 0x0000ffff;
2136 target_address = immediate;
2137 offset = calc_fixup (target_address, 0, sec);
2138 immediate -= offset;
2139 irelscan->r_addend -= offset;
2140 microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
2141 irelscan->r_addend);
2145 if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64
2146 || (ELF32_R_TYPE (irelscan->r_info)
2147 == (int) R_MICROBLAZE_TEXTREL_64))
2149 isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2151 /* Look at the reloc only if the value has been resolved. */
2152 if (isym->st_shndx == shndx
2153 && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2155 if (ocontents == NULL)
2157 if (elf_section_data (o)->this_hdr.contents != NULL)
2158 ocontents = elf_section_data (o)->this_hdr.contents;
2159 else
2161 /* We always cache the section contents.
2162 Perhaps, if info->keep_memory is FALSE, we
2163 should free them, if we are permitted to. */
2165 if (o->rawsize == 0)
2166 o->rawsize = o->size;
2167 ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2168 if (ocontents == NULL)
2169 goto error_return;
2170 if (!bfd_get_section_contents (abfd, o, ocontents,
2171 (file_ptr) 0,
2172 o->rawsize))
2173 goto error_return;
2174 elf_section_data (o)->this_hdr.contents = ocontents;
2177 offset = calc_fixup (irelscan->r_addend, 0, sec);
2178 irelscan->r_addend -= offset;
2181 else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_PCREL)
2183 isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
2185 /* Look at the reloc only if the value has been resolved. */
2186 if (isym->st_shndx == shndx
2187 && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
2189 bfd_vma immediate;
2190 bfd_vma target_address;
2192 if (ocontents == NULL)
2194 if (elf_section_data (o)->this_hdr.contents != NULL)
2195 ocontents = elf_section_data (o)->this_hdr.contents;
2196 else
2198 /* We always cache the section contents.
2199 Perhaps, if info->keep_memory is FALSE, we
2200 should free them, if we are permitted to. */
2201 if (o->rawsize == 0)
2202 o->rawsize = o->size;
2203 ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2204 if (ocontents == NULL)
2205 goto error_return;
2206 if (!bfd_get_section_contents (abfd, o, ocontents,
2207 (file_ptr) 0,
2208 o->rawsize))
2209 goto error_return;
2210 elf_section_data (o)->this_hdr.contents = ocontents;
2213 unsigned long instr_hi = bfd_get_32 (abfd, ocontents
2214 + irelscan->r_offset);
2215 unsigned long instr_lo = bfd_get_32 (abfd, ocontents
2216 + irelscan->r_offset
2217 + INST_WORD_SIZE);
2218 immediate = (instr_hi & 0x0000ffff) << 16;
2219 immediate |= (instr_lo & 0x0000ffff);
2220 target_address = immediate;
2221 offset = calc_fixup (target_address, 0, sec);
2222 immediate -= offset;
2223 irelscan->r_addend -= offset;
2224 microblaze_bfd_write_imm_value_64 (abfd, ocontents
2225 + irelscan->r_offset, immediate);
2231 /* Adjust the local symbols defined in this section. */
2232 isymend = isymbuf + symtab_hdr->sh_info;
2233 for (isym = isymbuf; isym < isymend; isym++)
2235 if (isym->st_shndx == shndx)
2237 isym->st_value -= calc_fixup (isym->st_value, 0, sec);
2238 if (isym->st_size)
2239 isym->st_size -= calc_fixup (isym->st_value, isym->st_size, sec);
2243 /* Now adjust the global symbols defined in this section. */
2244 isym = isymbuf + symtab_hdr->sh_info;
2245 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)) - symtab_hdr->sh_info;
2246 for (sym_index = 0; sym_index < symcount; sym_index++)
2248 sym_hash = elf_sym_hashes (abfd)[sym_index];
2249 if ((sym_hash->root.type == bfd_link_hash_defined
2250 || sym_hash->root.type == bfd_link_hash_defweak)
2251 && sym_hash->root.u.def.section == sec)
2253 sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
2254 0, sec);
2255 if (sym_hash->size)
2256 sym_hash->size -= calc_fixup (sym_hash->root.u.def.value,
2257 sym_hash->size, sec);
2261 /* Physically move the code and change the cooked size. */
2262 dest = sdata->relax[0].addr;
2263 for (i = 0; i < sdata->relax_count; i++)
2265 size_t len;
2266 src = sdata->relax[i].addr + sdata->relax[i].size;
2267 len = (sdata->relax[i+1].addr - sdata->relax[i].addr
2268 - sdata->relax[i].size);
2270 memmove (contents + dest, contents + src, len);
2271 sec->size -= sdata->relax[i].size;
2272 dest += len;
2275 elf_section_data (sec)->relocs = internal_relocs;
2276 free_relocs = NULL;
2278 elf_section_data (sec)->this_hdr.contents = contents;
2279 free_contents = NULL;
2281 symtab_hdr->contents = (bfd_byte *) isymbuf;
2284 free (free_relocs);
2285 free_relocs = NULL;
2287 if (free_contents != NULL)
2289 if (!link_info->keep_memory)
2290 free (free_contents);
2291 else
2292 /* Cache the section contents for elf_link_input_bfd. */
2293 elf_section_data (sec)->this_hdr.contents = contents;
2294 free_contents = NULL;
2297 if (sdata->relax_count == 0)
2299 *again = false;
2300 free (sdata->relax);
2301 sdata->relax = NULL;
2303 else
2304 *again = true;
2305 return true;
2307 error_return:
2308 free (free_relocs);
2309 free (free_contents);
2310 free (sdata->relax);
2311 sdata->relax = NULL;
2312 sdata->relax_count = 0;
2313 return false;
2316 /* Return the section that should be marked against GC for a given
2317 relocation. */
2319 static asection *
2320 microblaze_elf_gc_mark_hook (asection *sec,
2321 struct bfd_link_info * info,
2322 Elf_Internal_Rela * rel,
2323 struct elf_link_hash_entry * h,
2324 Elf_Internal_Sym * sym)
2326 if (h != NULL)
2327 switch (ELF32_R_TYPE (rel->r_info))
2329 case R_MICROBLAZE_GNU_VTINHERIT:
2330 case R_MICROBLAZE_GNU_VTENTRY:
2331 return NULL;
2334 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
2337 /* PIC support. */
2339 #define PLT_ENTRY_SIZE 16
2341 #define PLT_ENTRY_WORD_0 0xb0000000 /* "imm 0". */
2342 #define PLT_ENTRY_WORD_1 0xe9940000 /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT. */
2343 #define PLT_ENTRY_WORD_1_NOPIC 0xe9800000 /* "lwi r12,r0,0" - non-PIC object. */
2344 #define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
2345 #define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
2347 static bool
2348 update_local_sym_info (bfd *abfd,
2349 Elf_Internal_Shdr *symtab_hdr,
2350 unsigned long r_symndx,
2351 unsigned int tls_type)
2353 bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
2354 unsigned char *local_got_tls_masks;
2356 if (local_got_refcounts == NULL)
2358 bfd_size_type size = symtab_hdr->sh_info;
2360 size *= (sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks));
2361 local_got_refcounts = bfd_zalloc (abfd, size);
2362 if (local_got_refcounts == NULL)
2363 return false;
2364 elf_local_got_refcounts (abfd) = local_got_refcounts;
2367 local_got_tls_masks =
2368 (unsigned char *) (local_got_refcounts + symtab_hdr->sh_info);
2369 local_got_tls_masks[r_symndx] |= tls_type;
2370 local_got_refcounts[r_symndx] += 1;
2372 return true;
2374 /* Look through the relocs for a section during the first phase. */
2376 static bool
2377 microblaze_elf_check_relocs (bfd * abfd,
2378 struct bfd_link_info * info,
2379 asection * sec,
2380 const Elf_Internal_Rela * relocs)
2382 Elf_Internal_Shdr * symtab_hdr;
2383 struct elf_link_hash_entry ** sym_hashes;
2384 const Elf_Internal_Rela * rel;
2385 const Elf_Internal_Rela * rel_end;
2386 struct elf32_mb_link_hash_table *htab;
2387 asection *sreloc = NULL;
2389 if (bfd_link_relocatable (info))
2390 return true;
2392 htab = elf32_mb_hash_table (info);
2393 if (htab == NULL)
2394 return false;
2396 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
2397 sym_hashes = elf_sym_hashes (abfd);
2399 rel_end = relocs + sec->reloc_count;
2401 for (rel = relocs; rel < rel_end; rel++)
2403 unsigned int r_type;
2404 struct elf_link_hash_entry * h;
2405 unsigned long r_symndx;
2406 unsigned char tls_type = 0;
2408 r_symndx = ELF32_R_SYM (rel->r_info);
2409 r_type = ELF32_R_TYPE (rel->r_info);
2411 if (r_symndx < symtab_hdr->sh_info)
2412 h = NULL;
2413 else
2415 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
2416 while (h->root.type == bfd_link_hash_indirect
2417 || h->root.type == bfd_link_hash_warning)
2418 h = (struct elf_link_hash_entry *) h->root.u.i.link;
2421 switch (r_type)
2423 /* This relocation describes the C++ object vtable hierarchy.
2424 Reconstruct it for later use during GC. */
2425 case R_MICROBLAZE_GNU_VTINHERIT:
2426 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
2427 return false;
2428 break;
2430 /* This relocation describes which C++ vtable entries are actually
2431 used. Record for later use during GC. */
2432 case R_MICROBLAZE_GNU_VTENTRY:
2433 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
2434 return false;
2435 break;
2437 /* This relocation requires .plt entry. */
2438 case R_MICROBLAZE_PLT_64:
2439 if (h != NULL)
2441 h->needs_plt = 1;
2442 h->plt.refcount += 1;
2444 break;
2446 /* This relocation requires .got entry. */
2447 case R_MICROBLAZE_TLSGD:
2448 tls_type |= (TLS_TLS | TLS_GD);
2449 goto dogottls;
2450 case R_MICROBLAZE_TLSLD:
2451 tls_type |= (TLS_TLS | TLS_LD);
2452 /* Fall through. */
2453 dogottls:
2454 sec->has_tls_reloc = 1;
2455 /* Fall through. */
2456 case R_MICROBLAZE_GOT_64:
2457 if (htab->elf.sgot == NULL)
2459 if (htab->elf.dynobj == NULL)
2460 htab->elf.dynobj = abfd;
2461 if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
2462 return false;
2464 if (h != NULL)
2466 h->got.refcount += 1;
2467 elf32_mb_hash_entry (h)->tls_mask |= tls_type;
2469 else
2471 if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
2472 return false;
2474 break;
2476 case R_MICROBLAZE_GOTOFF_64:
2477 case R_MICROBLAZE_GOTOFF_32:
2478 if (htab->elf.sgot == NULL)
2480 if (htab->elf.dynobj == NULL)
2481 htab->elf.dynobj = abfd;
2482 if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
2483 return false;
2485 break;
2487 case R_MICROBLAZE_64:
2488 case R_MICROBLAZE_64_PCREL:
2489 case R_MICROBLAZE_32:
2491 if (h != NULL && !bfd_link_pic (info))
2493 /* we may need a copy reloc. */
2494 h->non_got_ref = 1;
2496 /* we may also need a .plt entry. */
2497 h->plt.refcount += 1;
2498 if (ELF32_R_TYPE (rel->r_info) != R_MICROBLAZE_64_PCREL)
2499 h->pointer_equality_needed = 1;
2503 /* If we are creating a shared library, and this is a reloc
2504 against a global symbol, or a non PC relative reloc
2505 against a local symbol, then we need to copy the reloc
2506 into the shared library. However, if we are linking with
2507 -Bsymbolic, we do not need to copy a reloc against a
2508 global symbol which is defined in an object we are
2509 including in the link (i.e., DEF_REGULAR is set). At
2510 this point we have not seen all the input files, so it is
2511 possible that DEF_REGULAR is not set now but will be set
2512 later (it is never cleared). In case of a weak definition,
2513 DEF_REGULAR may be cleared later by a strong definition in
2514 a shared library. We account for that possibility below by
2515 storing information in the relocs_copied field of the hash
2516 table entry. A similar situation occurs when creating
2517 shared libraries and symbol visibility changes render the
2518 symbol local.
2520 If on the other hand, we are creating an executable, we
2521 may need to keep relocations for symbols satisfied by a
2522 dynamic library if we manage to avoid copy relocs for the
2523 symbol. */
2525 if ((bfd_link_pic (info)
2526 && (sec->flags & SEC_ALLOC) != 0
2527 && (r_type != R_MICROBLAZE_64_PCREL
2528 || (h != NULL
2529 && (! info->symbolic
2530 || h->root.type == bfd_link_hash_defweak
2531 || !h->def_regular))))
2532 || (!bfd_link_pic (info)
2533 && (sec->flags & SEC_ALLOC) != 0
2534 && h != NULL
2535 && (h->root.type == bfd_link_hash_defweak
2536 || !h->def_regular)))
2538 struct elf_dyn_relocs *p;
2539 struct elf_dyn_relocs **head;
2541 /* When creating a shared object, we must copy these
2542 relocs into the output file. We create a reloc
2543 section in dynobj and make room for the reloc. */
2545 if (sreloc == NULL)
2547 bfd *dynobj;
2549 if (htab->elf.dynobj == NULL)
2550 htab->elf.dynobj = abfd;
2551 dynobj = htab->elf.dynobj;
2553 sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
2554 2, abfd, 1);
2555 if (sreloc == NULL)
2556 return false;
2559 /* If this is a global symbol, we count the number of
2560 relocations we need for this symbol. */
2561 if (h != NULL)
2562 head = &h->dyn_relocs;
2563 else
2565 /* Track dynamic relocs needed for local syms too.
2566 We really need local syms available to do this
2567 easily. Oh well. */
2569 asection *s;
2570 Elf_Internal_Sym *isym;
2571 void *vpp;
2573 isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
2574 abfd, r_symndx);
2575 if (isym == NULL)
2576 return false;
2578 s = bfd_section_from_elf_index (abfd, isym->st_shndx);
2579 if (s == NULL)
2580 return false;
2582 vpp = &elf_section_data (s)->local_dynrel;
2583 head = (struct elf_dyn_relocs **) vpp;
2586 p = *head;
2587 if (p == NULL || p->sec != sec)
2589 size_t amt = sizeof *p;
2590 p = ((struct elf_dyn_relocs *)
2591 bfd_alloc (htab->elf.dynobj, amt));
2592 if (p == NULL)
2593 return false;
2594 p->next = *head;
2595 *head = p;
2596 p->sec = sec;
2597 p->count = 0;
2598 p->pc_count = 0;
2601 p->count += 1;
2602 if (r_type == R_MICROBLAZE_64_PCREL)
2603 p->pc_count += 1;
2606 break;
2610 return true;
2613 /* Copy the extra info we tack onto an elf_link_hash_entry. */
2615 static void
2616 microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
2617 struct elf_link_hash_entry *dir,
2618 struct elf_link_hash_entry *ind)
2620 struct elf32_mb_link_hash_entry *edir, *eind;
2622 edir = (struct elf32_mb_link_hash_entry *) dir;
2623 eind = (struct elf32_mb_link_hash_entry *) ind;
2625 edir->tls_mask |= eind->tls_mask;
2627 _bfd_elf_link_hash_copy_indirect (info, dir, ind);
2630 static bool
2631 microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
2632 struct elf_link_hash_entry *h)
2634 struct elf32_mb_link_hash_table *htab;
2635 asection *s, *srel;
2636 unsigned int power_of_two;
2638 htab = elf32_mb_hash_table (info);
2639 if (htab == NULL)
2640 return false;
2642 /* If this is a function, put it in the procedure linkage table. We
2643 will fill in the contents of the procedure linkage table later,
2644 when we know the address of the .got section. */
2645 if (h->type == STT_FUNC
2646 || h->needs_plt)
2648 if (h->plt.refcount <= 0
2649 || SYMBOL_CALLS_LOCAL (info, h)
2650 || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
2651 && h->root.type == bfd_link_hash_undefweak))
2653 /* This case can occur if we saw a PLT reloc in an input
2654 file, but the symbol was never referred to by a dynamic
2655 object, or if all references were garbage collected. In
2656 such a case, we don't actually need to build a procedure
2657 linkage table, and we can just do a PC32 reloc instead. */
2658 h->plt.offset = (bfd_vma) -1;
2659 h->needs_plt = 0;
2662 return true;
2664 else
2665 /* It's possible that we incorrectly decided a .plt reloc was
2666 needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
2667 check_relocs. We can't decide accurately between function and
2668 non-function syms in check-relocs; Objects loaded later in
2669 the link may change h->type. So fix it now. */
2670 h->plt.offset = (bfd_vma) -1;
2672 /* If this is a weak symbol, and there is a real definition, the
2673 processor independent code will have arranged for us to see the
2674 real definition first, and we can just use the same value. */
2675 if (h->is_weakalias)
2677 struct elf_link_hash_entry *def = weakdef (h);
2678 BFD_ASSERT (def->root.type == bfd_link_hash_defined);
2679 h->root.u.def.section = def->root.u.def.section;
2680 h->root.u.def.value = def->root.u.def.value;
2681 return true;
2684 /* This is a reference to a symbol defined by a dynamic object which
2685 is not a function. */
2687 /* If we are creating a shared library, we must presume that the
2688 only references to the symbol are via the global offset table.
2689 For such cases we need not do anything here; the relocations will
2690 be handled correctly by relocate_section. */
2691 if (bfd_link_pic (info))
2692 return true;
2694 /* If there are no references to this symbol that do not use the
2695 GOT, we don't need to generate a copy reloc. */
2696 if (!h->non_got_ref)
2697 return true;
2699 /* If -z nocopyreloc was given, we won't generate them either. */
2700 if (info->nocopyreloc)
2702 h->non_got_ref = 0;
2703 return true;
2706 /* If we don't find any dynamic relocs in read-only sections, then
2707 we'll be keeping the dynamic relocs and avoiding the copy reloc. */
2708 if (!_bfd_elf_readonly_dynrelocs (h))
2710 h->non_got_ref = 0;
2711 return true;
2714 /* We must allocate the symbol in our .dynbss section, which will
2715 become part of the .bss section of the executable. There will be
2716 an entry for this symbol in the .dynsym section. The dynamic
2717 object will contain position independent code, so all references
2718 from the dynamic object to this symbol will go through the global
2719 offset table. The dynamic linker will use the .dynsym entry to
2720 determine the address it must put in the global offset table, so
2721 both the dynamic object and the regular object will refer to the
2722 same memory location for the variable. */
2724 /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
2725 to copy the initial value out of the dynamic object and into the
2726 runtime process image. */
2727 if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
2729 s = htab->elf.sdynrelro;
2730 srel = htab->elf.sreldynrelro;
2732 else
2734 s = htab->elf.sdynbss;
2735 srel = htab->elf.srelbss;
2737 if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
2739 srel->size += sizeof (Elf32_External_Rela);
2740 h->needs_copy = 1;
2743 /* We need to figure out the alignment required for this symbol. I
2744 have no idea how ELF linkers handle this. */
2745 power_of_two = bfd_log2 (h->size);
2746 if (power_of_two > 3)
2747 power_of_two = 3;
2749 /* Apply the required alignment. */
2750 s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
2751 if (power_of_two > s->alignment_power)
2753 if (!bfd_set_section_alignment (s, power_of_two))
2754 return false;
2757 /* Define the symbol as being at this point in the section. */
2758 h->root.u.def.section = s;
2759 h->root.u.def.value = s->size;
2761 /* Increment the section size to make room for the symbol. */
2762 s->size += h->size;
2763 return true;
2766 /* Allocate space in .plt, .got and associated reloc sections for
2767 dynamic relocs. */
2769 static bool
2770 allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
2772 struct bfd_link_info *info;
2773 struct elf32_mb_link_hash_table *htab;
2774 struct elf32_mb_link_hash_entry *eh;
2775 struct elf_dyn_relocs *p;
2777 if (h->root.type == bfd_link_hash_indirect)
2778 return true;
2780 info = (struct bfd_link_info *) dat;
2781 htab = elf32_mb_hash_table (info);
2782 if (htab == NULL)
2783 return false;
2785 if (htab->elf.dynamic_sections_created
2786 && h->plt.refcount > 0)
2788 /* Make sure this symbol is output as a dynamic symbol.
2789 Undefined weak syms won't yet be marked as dynamic. */
2790 if (h->dynindx == -1
2791 && !h->forced_local)
2793 if (! bfd_elf_link_record_dynamic_symbol (info, h))
2794 return false;
2797 if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
2799 asection *s = htab->elf.splt;
2801 /* The first entry in .plt is reserved. */
2802 if (s->size == 0)
2803 s->size = PLT_ENTRY_SIZE;
2805 h->plt.offset = s->size;
2807 /* If this symbol is not defined in a regular file, and we are
2808 not generating a shared library, then set the symbol to this
2809 location in the .plt. This is required to make function
2810 pointers compare as equal between the normal executable and
2811 the shared library. */
2812 if (! bfd_link_pic (info)
2813 && !h->def_regular)
2815 h->root.u.def.section = s;
2816 h->root.u.def.value = h->plt.offset;
2819 /* Make room for this entry. */
2820 s->size += PLT_ENTRY_SIZE;
2822 /* We also need to make an entry in the .got.plt section, which
2823 will be placed in the .got section by the linker script. */
2824 htab->elf.sgotplt->size += 4;
2826 /* We also need to make an entry in the .rel.plt section. */
2827 htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
2829 else
2831 h->plt.offset = (bfd_vma) -1;
2832 h->needs_plt = 0;
2835 else
2837 h->plt.offset = (bfd_vma) -1;
2838 h->needs_plt = 0;
2841 eh = (struct elf32_mb_link_hash_entry *) h;
2842 if (h->got.refcount > 0)
2844 unsigned int need;
2845 asection *s;
2847 /* Make sure this symbol is output as a dynamic symbol.
2848 Undefined weak syms won't yet be marked as dynamic. */
2849 if (h->dynindx == -1
2850 && !h->forced_local)
2852 if (! bfd_elf_link_record_dynamic_symbol (info, h))
2853 return false;
2856 need = 0;
2857 if ((eh->tls_mask & TLS_TLS) != 0)
2859 /* Handle TLS Symbol */
2860 if ((eh->tls_mask & TLS_LD) != 0)
2862 if (!eh->elf.def_dynamic)
2863 /* We'll just use htab->tlsld_got.offset. This should
2864 always be the case. It's a little odd if we have
2865 a local dynamic reloc against a non-local symbol. */
2866 htab->tlsld_got.refcount += 1;
2867 else
2868 need += 8;
2870 if ((eh->tls_mask & TLS_GD) != 0)
2871 need += 8;
2873 else
2875 /* Regular (non-TLS) symbol */
2876 need += 4;
2878 if (need == 0)
2880 h->got.offset = (bfd_vma) -1;
2882 else
2884 s = htab->elf.sgot;
2885 h->got.offset = s->size;
2886 s->size += need;
2887 htab->elf.srelgot->size += need * (sizeof (Elf32_External_Rela) / 4);
2890 else
2891 h->got.offset = (bfd_vma) -1;
2893 if (h->dyn_relocs == NULL)
2894 return true;
2896 /* In the shared -Bsymbolic case, discard space allocated for
2897 dynamic pc-relative relocs against symbols which turn out to be
2898 defined in regular objects. For the normal shared case, discard
2899 space for pc-relative relocs that have become local due to symbol
2900 visibility changes. */
2902 if (bfd_link_pic (info))
2904 if (h->def_regular
2905 && (h->forced_local
2906 || info->symbolic))
2908 struct elf_dyn_relocs **pp;
2910 for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
2912 p->count -= p->pc_count;
2913 p->pc_count = 0;
2914 if (p->count == 0)
2915 *pp = p->next;
2916 else
2917 pp = &p->next;
2920 else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
2921 h->dyn_relocs = NULL;
2923 else
2925 /* For the non-shared case, discard space for relocs against
2926 symbols which turn out to need copy relocs or are not
2927 dynamic. */
2929 if (!h->non_got_ref
2930 && ((h->def_dynamic
2931 && !h->def_regular)
2932 || (htab->elf.dynamic_sections_created
2933 && (h->root.type == bfd_link_hash_undefweak
2934 || h->root.type == bfd_link_hash_undefined))))
2936 /* Make sure this symbol is output as a dynamic symbol.
2937 Undefined weak syms won't yet be marked as dynamic. */
2938 if (h->dynindx == -1
2939 && !h->forced_local)
2941 if (! bfd_elf_link_record_dynamic_symbol (info, h))
2942 return false;
2945 /* If that succeeded, we know we'll be keeping all the
2946 relocs. */
2947 if (h->dynindx != -1)
2948 goto keep;
2951 h->dyn_relocs = NULL;
2953 keep: ;
2956 /* Finally, allocate space. */
2957 for (p = h->dyn_relocs; p != NULL; p = p->next)
2959 asection *sreloc = elf_section_data (p->sec)->sreloc;
2960 sreloc->size += p->count * sizeof (Elf32_External_Rela);
2963 return true;
2966 /* Set the sizes of the dynamic sections. */
2968 static bool
2969 microblaze_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
2970 struct bfd_link_info *info)
2972 struct elf32_mb_link_hash_table *htab;
2973 bfd *dynobj;
2974 asection *s;
2975 bfd *ibfd;
2977 htab = elf32_mb_hash_table (info);
2978 if (htab == NULL)
2979 return false;
2981 dynobj = htab->elf.dynobj;
2982 if (dynobj == NULL)
2983 return true;
2985 /* Set up .got offsets for local syms, and space for local dynamic
2986 relocs. */
2987 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
2989 bfd_signed_vma *local_got;
2990 bfd_signed_vma *end_local_got;
2991 bfd_size_type locsymcount;
2992 Elf_Internal_Shdr *symtab_hdr;
2993 unsigned char *lgot_masks;
2994 asection *srel;
2996 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
2997 continue;
2999 for (s = ibfd->sections; s != NULL; s = s->next)
3001 struct elf_dyn_relocs *p;
3003 for (p = ((struct elf_dyn_relocs *)
3004 elf_section_data (s)->local_dynrel);
3005 p != NULL;
3006 p = p->next)
3008 if (!bfd_is_abs_section (p->sec)
3009 && bfd_is_abs_section (p->sec->output_section))
3011 /* Input section has been discarded, either because
3012 it is a copy of a linkonce section or due to
3013 linker script /DISCARD/, so we'll be discarding
3014 the relocs too. */
3016 else if (p->count != 0)
3018 srel = elf_section_data (p->sec)->sreloc;
3019 srel->size += p->count * sizeof (Elf32_External_Rela);
3020 if ((p->sec->output_section->flags & SEC_READONLY) != 0)
3021 info->flags |= DF_TEXTREL;
3026 local_got = elf_local_got_refcounts (ibfd);
3027 if (!local_got)
3028 continue;
3030 symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
3031 locsymcount = symtab_hdr->sh_info;
3032 end_local_got = local_got + locsymcount;
3033 lgot_masks = (unsigned char *) end_local_got;
3034 s = htab->elf.sgot;
3035 srel = htab->elf.srelgot;
3037 for (; local_got < end_local_got; ++local_got, ++lgot_masks)
3039 if (*local_got > 0)
3041 unsigned int need = 0;
3042 if ((*lgot_masks & TLS_TLS) != 0)
3044 if ((*lgot_masks & TLS_GD) != 0)
3045 need += 8;
3046 if ((*lgot_masks & TLS_LD) != 0)
3047 htab->tlsld_got.refcount += 1;
3049 else
3050 need += 4;
3052 if (need == 0)
3054 *local_got = (bfd_vma) -1;
3056 else
3058 *local_got = s->size;
3059 s->size += need;
3060 if (bfd_link_pic (info))
3061 srel->size += need * (sizeof (Elf32_External_Rela) / 4);
3064 else
3065 *local_got = (bfd_vma) -1;
3069 /* Allocate global sym .plt and .got entries, and space for global
3070 sym dynamic relocs. */
3071 elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
3073 if (htab->tlsld_got.refcount > 0)
3075 htab->tlsld_got.offset = htab->elf.sgot->size;
3076 htab->elf.sgot->size += 8;
3077 if (bfd_link_pic (info))
3078 htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
3080 else
3081 htab->tlsld_got.offset = (bfd_vma) -1;
3083 if (elf_hash_table (info)->dynamic_sections_created)
3085 /* Make space for the trailing nop in .plt. */
3086 if (htab->elf.splt->size > 0)
3087 htab->elf.splt->size += 4;
3090 /* The check_relocs and adjust_dynamic_symbol entry points have
3091 determined the sizes of the various dynamic sections. Allocate
3092 memory for them. */
3093 for (s = dynobj->sections; s != NULL; s = s->next)
3095 const char *name;
3096 bool strip = false;
3098 if ((s->flags & SEC_LINKER_CREATED) == 0)
3099 continue;
3101 /* It's OK to base decisions on the section name, because none
3102 of the dynobj section names depend upon the input files. */
3103 name = bfd_section_name (s);
3105 if (startswith (name, ".rela"))
3107 if (s->size == 0)
3109 /* If we don't need this section, strip it from the
3110 output file. This is to handle .rela.bss and
3111 .rela.plt. We must create it in
3112 create_dynamic_sections, because it must be created
3113 before the linker maps input sections to output
3114 sections. The linker does that before
3115 adjust_dynamic_symbol is called, and it is that
3116 function which decides whether anything needs to go
3117 into these sections. */
3118 strip = true;
3120 else
3122 /* We use the reloc_count field as a counter if we need
3123 to copy relocs into the output file. */
3124 s->reloc_count = 0;
3127 else if (s != htab->elf.splt
3128 && s != htab->elf.sgot
3129 && s != htab->elf.sgotplt
3130 && s != htab->elf.sdynbss
3131 && s != htab->elf.sdynrelro)
3133 /* It's not one of our sections, so don't allocate space. */
3134 continue;
3137 if (strip)
3139 s->flags |= SEC_EXCLUDE;
3140 continue;
3143 /* Allocate memory for the section contents. */
3144 /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
3145 Unused entries should be reclaimed before the section's contents
3146 are written out, but at the moment this does not happen. Thus in
3147 order to prevent writing out garbage, we initialise the section's
3148 contents to zero. */
3149 s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
3150 if (s->contents == NULL && s->size != 0)
3151 return false;
3154 /* ??? Force DF_BIND_NOW? */
3155 info->flags |= DF_BIND_NOW;
3156 return _bfd_elf_add_dynamic_tags (output_bfd, info, true);
3159 /* Finish up dynamic symbol handling. We set the contents of various
3160 dynamic sections here. */
3162 static bool
3163 microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
3164 struct bfd_link_info *info,
3165 struct elf_link_hash_entry *h,
3166 Elf_Internal_Sym *sym)
3168 struct elf32_mb_link_hash_table *htab;
3169 struct elf32_mb_link_hash_entry *eh = elf32_mb_hash_entry(h);
3171 htab = elf32_mb_hash_table (info);
3173 if (h->plt.offset != (bfd_vma) -1)
3175 asection *splt;
3176 asection *srela;
3177 asection *sgotplt;
3178 Elf_Internal_Rela rela;
3179 bfd_byte *loc;
3180 bfd_vma plt_index;
3181 bfd_vma got_offset;
3182 bfd_vma got_addr;
3184 /* This symbol has an entry in the procedure linkage table. Set
3185 it up. */
3186 BFD_ASSERT (h->dynindx != -1);
3188 splt = htab->elf.splt;
3189 srela = htab->elf.srelplt;
3190 sgotplt = htab->elf.sgotplt;
3191 BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
3193 plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved. */
3194 got_offset = (plt_index + 3) * 4; /* 3 reserved ??? */
3195 got_addr = got_offset;
3197 /* For non-PIC objects we need absolute address of the GOT entry. */
3198 if (!bfd_link_pic (info))
3199 got_addr += sgotplt->output_section->vma + sgotplt->output_offset;
3201 /* Fill in the entry in the procedure linkage table. */
3202 bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
3203 splt->contents + h->plt.offset);
3204 if (bfd_link_pic (info))
3205 bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
3206 splt->contents + h->plt.offset + 4);
3207 else
3208 bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
3209 splt->contents + h->plt.offset + 4);
3210 bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
3211 splt->contents + h->plt.offset + 8);
3212 bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
3213 splt->contents + h->plt.offset + 12);
3215 /* Any additions to the .got section??? */
3216 /* bfd_put_32 (output_bfd,
3217 splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
3218 sgotplt->contents + got_offset); */
3220 /* Fill in the entry in the .rela.plt section. */
3221 rela.r_offset = (sgotplt->output_section->vma
3222 + sgotplt->output_offset
3223 + got_offset);
3224 rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
3225 rela.r_addend = 0;
3226 loc = srela->contents;
3227 loc += plt_index * sizeof (Elf32_External_Rela);
3228 bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3230 if (!h->def_regular)
3232 /* Mark the symbol as undefined, rather than as defined in
3233 the .plt section. Zero the value. */
3234 sym->st_shndx = SHN_UNDEF;
3235 sym->st_value = 0;
3239 /* h->got.refcount to be checked ? */
3240 if ((h->got.offset != (bfd_vma) -1)
3241 && ! ((h->got.offset & 1)
3242 || IS_TLS_LD(eh->tls_mask) || IS_TLS_GD(eh->tls_mask)))
3244 asection *sgot;
3245 asection *srela;
3246 bfd_vma offset;
3248 /* This symbol has an entry in the global offset table. Set it
3249 up. */
3251 sgot = htab->elf.sgot;
3252 srela = htab->elf.srelgot;
3253 BFD_ASSERT (sgot != NULL && srela != NULL);
3255 offset = (sgot->output_section->vma + sgot->output_offset
3256 + (h->got.offset &~ (bfd_vma) 1));
3258 /* If this is a -Bsymbolic link, and the symbol is defined
3259 locally, we just want to emit a RELATIVE reloc. Likewise if
3260 the symbol was forced to be local because of a version file.
3261 The entry in the global offset table will already have been
3262 initialized in the relocate_section function. */
3263 if (bfd_link_pic (info)
3264 && ((info->symbolic && h->def_regular)
3265 || h->dynindx == -1))
3267 asection *sec = h->root.u.def.section;
3268 bfd_vma value;
3270 value = h->root.u.def.value;
3271 if (sec->output_section != NULL)
3272 /* PR 21180: If the output section is NULL, then the symbol is no
3273 longer needed, and in theory the GOT entry is redundant. But
3274 it is too late to change our minds now... */
3275 value += sec->output_section->vma + sec->output_offset;
3277 microblaze_elf_output_dynamic_relocation (output_bfd,
3278 srela, srela->reloc_count++,
3279 /* symindex= */ 0,
3280 R_MICROBLAZE_REL, offset,
3281 value);
3283 else
3285 microblaze_elf_output_dynamic_relocation (output_bfd,
3286 srela, srela->reloc_count++,
3287 h->dynindx,
3288 R_MICROBLAZE_GLOB_DAT,
3289 offset, 0);
3292 bfd_put_32 (output_bfd, (bfd_vma) 0,
3293 sgot->contents + (h->got.offset &~ (bfd_vma) 1));
3296 if (h->needs_copy)
3298 asection *s;
3299 Elf_Internal_Rela rela;
3300 bfd_byte *loc;
3302 /* This symbols needs a copy reloc. Set it up. */
3304 BFD_ASSERT (h->dynindx != -1);
3306 rela.r_offset = (h->root.u.def.value
3307 + h->root.u.def.section->output_section->vma
3308 + h->root.u.def.section->output_offset);
3309 rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
3310 rela.r_addend = 0;
3311 if (h->root.u.def.section == htab->elf.sdynrelro)
3312 s = htab->elf.sreldynrelro;
3313 else
3314 s = htab->elf.srelbss;
3315 loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
3316 bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3319 /* Mark some specially defined symbols as absolute. */
3320 if (h == htab->elf.hdynamic
3321 || h == htab->elf.hgot
3322 || h == htab->elf.hplt)
3323 sym->st_shndx = SHN_ABS;
3325 return true;
3329 /* Finish up the dynamic sections. */
3331 static bool
3332 microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
3333 struct bfd_link_info *info)
3335 bfd *dynobj;
3336 asection *sdyn, *sgot;
3337 struct elf32_mb_link_hash_table *htab;
3339 htab = elf32_mb_hash_table (info);
3340 if (htab == NULL)
3341 return false;
3343 dynobj = htab->elf.dynobj;
3345 sdyn = bfd_get_linker_section (dynobj, ".dynamic");
3347 if (htab->elf.dynamic_sections_created)
3349 asection *splt;
3350 Elf32_External_Dyn *dyncon, *dynconend;
3352 dyncon = (Elf32_External_Dyn *) sdyn->contents;
3353 dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
3354 for (; dyncon < dynconend; dyncon++)
3356 Elf_Internal_Dyn dyn;
3357 asection *s;
3358 bool size;
3360 bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
3362 switch (dyn.d_tag)
3364 case DT_PLTGOT:
3365 s = htab->elf.sgotplt;
3366 size = false;
3367 break;
3369 case DT_PLTRELSZ:
3370 s = htab->elf.srelplt;
3371 size = true;
3372 break;
3374 case DT_JMPREL:
3375 s = htab->elf.srelplt;
3376 size = false;
3377 break;
3379 default:
3380 continue;
3383 if (s == NULL)
3384 dyn.d_un.d_val = 0;
3385 else
3387 if (!size)
3388 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3389 else
3390 dyn.d_un.d_val = s->size;
3392 bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
3395 splt = htab->elf.splt;
3396 BFD_ASSERT (splt != NULL && sdyn != NULL);
3398 /* Clear the first entry in the procedure linkage table,
3399 and put a nop in the last four bytes. */
3400 if (splt->size > 0)
3402 memset (splt->contents, 0, PLT_ENTRY_SIZE);
3403 bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop. */,
3404 splt->contents + splt->size - 4);
3406 if (splt->output_section != bfd_abs_section_ptr)
3407 elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
3411 /* Set the first entry in the global offset table to the address of
3412 the dynamic section. */
3413 sgot = htab->elf.sgotplt;
3414 if (sgot && sgot->size > 0)
3416 if (sdyn == NULL)
3417 bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
3418 else
3419 bfd_put_32 (output_bfd,
3420 sdyn->output_section->vma + sdyn->output_offset,
3421 sgot->contents);
3422 elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
3425 if (htab->elf.sgot && htab->elf.sgot->size > 0)
3426 elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
3428 return true;
3431 /* Hook called by the linker routine which adds symbols from an object
3432 file. We use it to put .comm items in .sbss, and not .bss. */
3434 static bool
3435 microblaze_elf_add_symbol_hook (bfd *abfd,
3436 struct bfd_link_info *info,
3437 Elf_Internal_Sym *sym,
3438 const char **namep ATTRIBUTE_UNUSED,
3439 flagword *flagsp ATTRIBUTE_UNUSED,
3440 asection **secp,
3441 bfd_vma *valp)
3443 if (sym->st_shndx == SHN_COMMON
3444 && !bfd_link_relocatable (info)
3445 && sym->st_size <= elf_gp_size (abfd))
3447 /* Common symbols less than or equal to -G nn bytes are automatically
3448 put into .sbss. */
3449 *secp = bfd_make_section_old_way (abfd, ".sbss");
3450 if (*secp == NULL
3451 || !bfd_set_section_flags (*secp, SEC_IS_COMMON | SEC_SMALL_DATA))
3452 return false;
3454 *valp = sym->st_size;
3457 return true;
3460 #define TARGET_LITTLE_SYM microblaze_elf32_le_vec
3461 #define TARGET_LITTLE_NAME "elf32-microblazeel"
3463 #define TARGET_BIG_SYM microblaze_elf32_vec
3464 #define TARGET_BIG_NAME "elf32-microblaze"
3466 #define ELF_ARCH bfd_arch_microblaze
3467 #define ELF_TARGET_ID MICROBLAZE_ELF_DATA
3468 #define ELF_MACHINE_CODE EM_MICROBLAZE
3469 #define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
3470 #define ELF_MAXPAGESIZE 0x1000
3471 #define elf_info_to_howto microblaze_elf_info_to_howto
3472 #define elf_info_to_howto_rel NULL
3474 #define bfd_elf32_bfd_reloc_type_lookup microblaze_elf_reloc_type_lookup
3475 #define bfd_elf32_bfd_is_local_label_name microblaze_elf_is_local_label_name
3476 #define bfd_elf32_new_section_hook microblaze_elf_new_section_hook
3477 #define elf_backend_relocate_section microblaze_elf_relocate_section
3478 #define bfd_elf32_bfd_relax_section microblaze_elf_relax_section
3479 #define bfd_elf32_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
3480 #define bfd_elf32_bfd_reloc_name_lookup microblaze_elf_reloc_name_lookup
3482 #define elf_backend_gc_mark_hook microblaze_elf_gc_mark_hook
3483 #define elf_backend_check_relocs microblaze_elf_check_relocs
3484 #define elf_backend_copy_indirect_symbol microblaze_elf_copy_indirect_symbol
3485 #define bfd_elf32_bfd_link_hash_table_create microblaze_elf_link_hash_table_create
3486 #define elf_backend_can_gc_sections 1
3487 #define elf_backend_can_refcount 1
3488 #define elf_backend_want_got_plt 1
3489 #define elf_backend_plt_readonly 1
3490 #define elf_backend_got_header_size 12
3491 #define elf_backend_want_dynrelro 1
3492 #define elf_backend_rela_normal 1
3493 #define elf_backend_dtrel_excludes_plt 1
3495 #define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
3496 #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
3497 #define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
3498 #define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
3499 #define elf_backend_late_size_sections microblaze_elf_late_size_sections
3500 #define elf_backend_add_symbol_hook microblaze_elf_add_symbol_hook
3502 #include "elf32-target.h"