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