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