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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [elf32-microblaze.c] - Blame information for rev 139

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

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

powered by: WebSVN 2.1.0

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