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