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