Coverage Report

Created: 2023-08-28 06:31

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