OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [bfd/] [elf32-microblaze.c] - Blame information for rev 841

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.