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