Coverage Report

Created: 2024-05-21 06:29

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