Coverage Report

Created: 2026-09-14 08:07

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