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 148

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
  info = (struct bfd_link_info *) dat;
2386
  htab = elf32_mb_hash_table (info);
2387
  if (htab == NULL)
2388
    return FALSE;
2389
 
2390
  if (htab->elf.dynamic_sections_created
2391
      && h->plt.refcount > 0)
2392
    {
2393
      /* Make sure this symbol is output as a dynamic symbol.
2394
         Undefined weak syms won't yet be marked as dynamic.  */
2395
      if (h->dynindx == -1
2396
          && !h->forced_local)
2397
        {
2398
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
2399
            return FALSE;
2400
        }
2401
 
2402
      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
2403
        {
2404
          asection *s = htab->splt;
2405
 
2406
          /* The first entry in .plt is reserved.  */
2407
          if (s->size == 0)
2408
            s->size = PLT_ENTRY_SIZE;
2409
 
2410
          h->plt.offset = s->size;
2411
 
2412
          /* If this symbol is not defined in a regular file, and we are
2413
             not generating a shared library, then set the symbol to this
2414
             location in the .plt.  This is required to make function
2415
             pointers compare as equal between the normal executable and
2416
             the shared library.  */
2417
          if (! info->shared
2418
              && !h->def_regular)
2419
            {
2420
              h->root.u.def.section = s;
2421
              h->root.u.def.value = h->plt.offset;
2422
            }
2423
 
2424
          /* Make room for this entry.  */
2425
          s->size += PLT_ENTRY_SIZE;
2426
 
2427
          /* We also need to make an entry in the .got.plt section, which
2428
             will be placed in the .got section by the linker script.  */
2429
          htab->sgotplt->size += 4;
2430
 
2431
          /* We also need to make an entry in the .rel.plt section.  */
2432
          htab->srelplt->size += sizeof (Elf32_External_Rela);
2433
        }
2434
      else
2435
        {
2436
          h->plt.offset = (bfd_vma) -1;
2437
          h->needs_plt = 0;
2438
        }
2439
    }
2440
  else
2441
    {
2442
      h->plt.offset = (bfd_vma) -1;
2443
      h->needs_plt = 0;
2444
    }
2445
 
2446
  if (h->got.refcount > 0)
2447
    {
2448
      asection *s;
2449
 
2450
      /* Make sure this symbol is output as a dynamic symbol.
2451
         Undefined weak syms won't yet be marked as dynamic.  */
2452
      if (h->dynindx == -1
2453
          && !h->forced_local)
2454
        {
2455
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
2456
            return FALSE;
2457
        }
2458
 
2459
      s = htab->sgot;
2460
      h->got.offset = s->size;
2461
      s->size += 4;
2462
      htab->srelgot->size += sizeof (Elf32_External_Rela);
2463
    }
2464
  else
2465
    h->got.offset = (bfd_vma) -1;
2466
 
2467
  eh = (struct elf32_mb_link_hash_entry *) h;
2468
  if (eh->dyn_relocs == NULL)
2469
    return TRUE;
2470
 
2471
  /* In the shared -Bsymbolic case, discard space allocated for
2472
     dynamic pc-relative relocs against symbols which turn out to be
2473
     defined in regular objects.  For the normal shared case, discard
2474
     space for pc-relative relocs that have become local due to symbol
2475
     visibility changes.  */
2476
 
2477
  if (info->shared)
2478
    {
2479
      if (h->def_regular
2480
          && (h->forced_local
2481
              || info->symbolic))
2482
        {
2483
          struct elf32_mb_dyn_relocs **pp;
2484
 
2485
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
2486
            {
2487
              p->count -= p->pc_count;
2488
              p->pc_count = 0;
2489
              if (p->count == 0)
2490
                *pp = p->next;
2491
              else
2492
                pp = &p->next;
2493
            }
2494
        }
2495
    }
2496
  else
2497
    {
2498
      /* For the non-shared case, discard space for relocs against
2499
         symbols which turn out to need copy relocs or are not
2500
         dynamic.  */
2501
 
2502
      if (!h->non_got_ref
2503
          && ((h->def_dynamic
2504
               && !h->def_regular)
2505
              || (htab->elf.dynamic_sections_created
2506
                  && (h->root.type == bfd_link_hash_undefweak
2507
                      || h->root.type == bfd_link_hash_undefined))))
2508
        {
2509
          /* Make sure this symbol is output as a dynamic symbol.
2510
             Undefined weak syms won't yet be marked as dynamic.  */
2511
          if (h->dynindx == -1
2512
              && !h->forced_local)
2513
            {
2514
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
2515
                return FALSE;
2516
            }
2517
 
2518
          /* If that succeeded, we know we'll be keeping all the
2519
             relocs.  */
2520
          if (h->dynindx != -1)
2521
            goto keep;
2522
        }
2523
 
2524
      eh->dyn_relocs = NULL;
2525
 
2526
    keep: ;
2527
    }
2528
 
2529
  /* Finally, allocate space.  */
2530
  for (p = eh->dyn_relocs; p != NULL; p = p->next)
2531
    {
2532
      asection *sreloc = elf_section_data (p->sec)->sreloc;
2533
      sreloc->size += p->count * sizeof (Elf32_External_Rela);
2534
    }
2535
 
2536
  return TRUE;
2537
}
2538
 
2539
/* Set the sizes of the dynamic sections.  */
2540
 
2541
static bfd_boolean
2542
microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
2543
                                      struct bfd_link_info *info)
2544
{
2545
  struct elf32_mb_link_hash_table *htab;
2546
  bfd *dynobj;
2547
  asection *s;
2548
  bfd *ibfd;
2549
 
2550
  htab = elf32_mb_hash_table (info);
2551
  if (htab == NULL)
2552
    return FALSE;
2553
 
2554
  dynobj = htab->elf.dynobj;
2555
  BFD_ASSERT (dynobj != NULL);
2556
 
2557
  /* Set up .got offsets for local syms, and space for local dynamic
2558
     relocs.  */
2559
  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
2560
    {
2561
      bfd_signed_vma *local_got;
2562
      bfd_signed_vma *end_local_got;
2563
      bfd_size_type locsymcount;
2564
      Elf_Internal_Shdr *symtab_hdr;
2565
      asection *srel;
2566
 
2567
      if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
2568
        continue;
2569
 
2570
      for (s = ibfd->sections; s != NULL; s = s->next)
2571
        {
2572
          struct elf32_mb_dyn_relocs *p;
2573
 
2574
          for (p = ((struct elf32_mb_dyn_relocs *)
2575
                    elf_section_data (s)->local_dynrel);
2576
               p != NULL;
2577
               p = p->next)
2578
            {
2579
              if (!bfd_is_abs_section (p->sec)
2580
                  && bfd_is_abs_section (p->sec->output_section))
2581
                {
2582
                  /* Input section has been discarded, either because
2583
                     it is a copy of a linkonce section or due to
2584
                     linker script /DISCARD/, so we'll be discarding
2585
                     the relocs too.  */
2586
                }
2587
              else if (p->count != 0)
2588
                {
2589
                  srel = elf_section_data (p->sec)->sreloc;
2590
                  srel->size += p->count * sizeof (Elf32_External_Rela);
2591
                  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
2592
                    info->flags |= DF_TEXTREL;
2593
                }
2594
            }
2595
        }
2596
 
2597
      local_got = elf_local_got_refcounts (ibfd);
2598
      if (!local_got)
2599
        continue;
2600
 
2601
      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
2602
      locsymcount = symtab_hdr->sh_info;
2603
      end_local_got = local_got + locsymcount;
2604
      s = htab->sgot;
2605
      srel = htab->srelgot;
2606
 
2607
      for (; local_got < end_local_got; ++local_got)
2608
        {
2609
          if (*local_got > 0)
2610
            {
2611
              *local_got = s->size;
2612
              s->size += 4;
2613
              if (info->shared)
2614
                srel->size += sizeof (Elf32_External_Rela);
2615
            }
2616
          else
2617
            *local_got = (bfd_vma) -1;
2618
        }
2619
    }
2620
 
2621
  /* Allocate global sym .plt and .got entries, and space for global
2622
     sym dynamic relocs.  */
2623
  elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
2624
 
2625
  if (elf_hash_table (info)->dynamic_sections_created)
2626
    {
2627
      /* Make space for the trailing nop in .plt.  */
2628
      if (htab->splt->size > 0)
2629
        htab->splt->size += 4;
2630
    }
2631
 
2632
  /* The check_relocs and adjust_dynamic_symbol entry points have
2633
     determined the sizes of the various dynamic sections.  Allocate
2634
     memory for them.  */
2635
  for (s = dynobj->sections; s != NULL; s = s->next)
2636
    {
2637
      const char *name;
2638
      bfd_boolean strip = FALSE;
2639
 
2640
      if ((s->flags & SEC_LINKER_CREATED) == 0)
2641
        continue;
2642
 
2643
      /* It's OK to base decisions on the section name, because none
2644
         of the dynobj section names depend upon the input files.  */
2645
      name = bfd_get_section_name (dynobj, s);
2646
 
2647
      if (strncmp (name, ".rela", 5) == 0)
2648
        {
2649
          if (s->size == 0)
2650
            {
2651
              /* If we don't need this section, strip it from the
2652
                 output file.  This is to handle .rela.bss and
2653
                 .rela.plt.  We must create it in
2654
                 create_dynamic_sections, because it must be created
2655
                 before the linker maps input sections to output
2656
                 sections.  The linker does that before
2657
                 adjust_dynamic_symbol is called, and it is that
2658
                 function which decides whether anything needs to go
2659
                 into these sections.  */
2660
              strip = TRUE;
2661
            }
2662
          else
2663
            {
2664
              /* We use the reloc_count field as a counter if we need
2665
                 to copy relocs into the output file.  */
2666
              s->reloc_count = 0;
2667
            }
2668
        }
2669
      else if (s != htab->splt && s != htab->sgot && s != htab->sgotplt)
2670
        {
2671
          /* It's not one of our sections, so don't allocate space.  */
2672
          continue;
2673
        }
2674
 
2675
      if (strip)
2676
        {
2677
          s->flags |= SEC_EXCLUDE;
2678
          continue;
2679
        }
2680
 
2681
      /* Allocate memory for the section contents.  */
2682
      /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
2683
         Unused entries should be reclaimed before the section's contents
2684
         are written out, but at the moment this does not happen.  Thus in
2685
         order to prevent writing out garbage, we initialise the section's
2686
         contents to zero.  */
2687
      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
2688
      if (s->contents == NULL && s->size != 0)
2689
        return FALSE;
2690
    }
2691
 
2692
  if (elf_hash_table (info)->dynamic_sections_created)
2693
    {
2694
      /* Add some entries to the .dynamic section.  We fill in the
2695
         values later, in microblaze_elf_finish_dynamic_sections, but we
2696
         must add the entries now so that we get the correct size for
2697
         the .dynamic section.  The DT_DEBUG entry is filled in by the
2698
         dynamic linker and used by the debugger.  */
2699
#define add_dynamic_entry(TAG, VAL)                     \
2700
      _bfd_elf_add_dynamic_entry (info, TAG, VAL)
2701
 
2702
      if (info->executable)
2703
        {
2704
          if (!add_dynamic_entry (DT_DEBUG, 0))
2705
            return FALSE;
2706
        }
2707
 
2708
      if (!add_dynamic_entry (DT_RELA, 0)
2709
          || !add_dynamic_entry (DT_RELASZ, 0)
2710
          || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
2711
        return FALSE;
2712
 
2713
      if (htab->splt->size != 0)
2714
        {
2715
          if (!add_dynamic_entry (DT_PLTGOT, 0)
2716
              || !add_dynamic_entry (DT_PLTRELSZ, 0)
2717
              || !add_dynamic_entry (DT_PLTREL, DT_RELA)
2718
              || !add_dynamic_entry (DT_JMPREL, 0)
2719
              || !add_dynamic_entry (DT_BIND_NOW, 1))
2720
            return FALSE;
2721
        }
2722
 
2723
      if (info->flags & DF_TEXTREL)
2724
        {
2725
          if (!add_dynamic_entry (DT_TEXTREL, 0))
2726
            return FALSE;
2727
        }
2728
    }
2729
#undef add_dynamic_entry
2730
  return TRUE;
2731
}
2732
 
2733
/* Finish up dynamic symbol handling.  We set the contents of various
2734
   dynamic sections here.  */
2735
 
2736
static bfd_boolean
2737
microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
2738
                                      struct bfd_link_info *info,
2739
                                      struct elf_link_hash_entry *h,
2740
                                      Elf_Internal_Sym *sym)
2741
{
2742
  struct elf32_mb_link_hash_table *htab;
2743
 
2744
  htab = elf32_mb_hash_table (info);
2745
  if (htab == NULL)
2746
    return FALSE;
2747
 
2748
  if (h->plt.offset != (bfd_vma) -1)
2749
    {
2750
      asection *splt;
2751
      asection *srela;
2752
      asection *sgotplt;
2753
      Elf_Internal_Rela rela;
2754
      bfd_byte *loc;
2755
      bfd_vma plt_index;
2756
      bfd_vma got_offset;
2757
      bfd_vma got_addr;
2758
 
2759
      /* This symbol has an entry in the procedure linkage table.  Set
2760
         it up.  */
2761
      BFD_ASSERT (h->dynindx != -1);
2762
 
2763
      splt = htab->splt;
2764
      srela = htab->srelplt;
2765
      sgotplt = htab->sgotplt;
2766
      BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
2767
 
2768
      plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved.  */
2769
      got_offset = (plt_index + 3) * 4; /* 3 reserved ???  */
2770
      got_addr = got_offset;
2771
 
2772
      /* For non-PIC objects we need absolute address of the GOT entry.  */
2773
      if (!info->shared)
2774
        got_addr += htab->sgotplt->output_section->vma + sgotplt->output_offset;
2775
 
2776
      /* Fill in the entry in the procedure linkage table.  */
2777
      bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
2778
                  splt->contents + h->plt.offset);
2779
      if (info->shared)
2780
        bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
2781
                    splt->contents + h->plt.offset + 4);
2782
      else
2783
        bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
2784
                    splt->contents + h->plt.offset + 4);
2785
      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
2786
                  splt->contents + h->plt.offset + 8);
2787
      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
2788
                  splt->contents + h->plt.offset + 12);
2789
 
2790
      /* Any additions to the .got section??? */
2791
      /*      bfd_put_32 (output_bfd,
2792
              splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
2793
              sgotplt->contents + got_offset); */
2794
 
2795
      /* Fill in the entry in the .rela.plt section.  */
2796
      rela.r_offset = (sgotplt->output_section->vma
2797
                       + sgotplt->output_offset
2798
                       + got_offset);
2799
      rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
2800
      rela.r_addend = 0;
2801
      loc = srela->contents;
2802
      loc += plt_index * sizeof (Elf32_External_Rela);
2803
      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
2804
 
2805
      if (!h->def_regular)
2806
        {
2807
          /* Mark the symbol as undefined, rather than as defined in
2808
             the .plt section.  Zero the value.  */
2809
          sym->st_shndx = SHN_UNDEF;
2810
          sym->st_value = 0;
2811
        }
2812
    }
2813
 
2814
  if (h->got.offset != (bfd_vma) -1)
2815
    {
2816
      asection *sgot;
2817
      asection *srela;
2818
      Elf_Internal_Rela rela;
2819
      bfd_byte *loc;
2820
 
2821
      /* This symbol has an entry in the global offset table.  Set it
2822
         up.  */
2823
 
2824
      sgot = htab->sgot;
2825
      srela = htab->srelgot;
2826
      BFD_ASSERT (sgot != NULL && srela != NULL);
2827
 
2828
      rela.r_offset = (sgot->output_section->vma
2829
                       + sgot->output_offset
2830
                       + (h->got.offset &~ (bfd_vma) 1));
2831
 
2832
      /* If this is a -Bsymbolic link, and the symbol is defined
2833
         locally, we just want to emit a RELATIVE reloc.  Likewise if
2834
         the symbol was forced to be local because of a version file.
2835
         The entry in the global offset table will already have been
2836
         initialized in the relocate_section function.  */
2837
      if (info->shared
2838
          && (info->symbolic || h->dynindx == -1)
2839
          && h->def_regular)
2840
        {
2841
          asection *sec = h->root.u.def.section;
2842
          rela.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
2843
          rela.r_addend = (h->root.u.def.value
2844
                           + sec->output_section->vma
2845
                           + sec->output_offset);
2846
        }
2847
      else
2848
        {
2849
          rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_GLOB_DAT);
2850
          rela.r_addend = 0;
2851
        }
2852
 
2853
      bfd_put_32 (output_bfd, (bfd_vma) 0,
2854
                  sgot->contents + (h->got.offset &~ (bfd_vma) 1));
2855
      loc = srela->contents;
2856
      loc += srela->reloc_count++ * sizeof (Elf32_External_Rela);
2857
      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
2858
    }
2859
 
2860
  if (h->needs_copy)
2861
    {
2862
      asection *s;
2863
      Elf_Internal_Rela rela;
2864
      bfd_byte *loc;
2865
 
2866
      /* This symbols needs a copy reloc.  Set it up.  */
2867
 
2868
      BFD_ASSERT (h->dynindx != -1);
2869
 
2870
      s = bfd_get_section_by_name (h->root.u.def.section->owner,
2871
                                   ".rela.bss");
2872
      BFD_ASSERT (s != NULL);
2873
 
2874
      rela.r_offset = (h->root.u.def.value
2875
                       + h->root.u.def.section->output_section->vma
2876
                       + h->root.u.def.section->output_offset);
2877
      rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
2878
      rela.r_addend = 0;
2879
      loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
2880
      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
2881
    }
2882
 
2883
  /* Mark some specially defined symbols as absolute.  */
2884
  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
2885
      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
2886
      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
2887
    sym->st_shndx = SHN_ABS;
2888
 
2889
  return TRUE;
2890
}
2891
 
2892
 
2893
/* Finish up the dynamic sections.  */
2894
 
2895
static bfd_boolean
2896
microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
2897
                                        struct bfd_link_info *info)
2898
{
2899
  bfd *dynobj;
2900
  asection *sdyn, *sgot;
2901
  struct elf32_mb_link_hash_table *htab;
2902
 
2903
  htab = elf32_mb_hash_table (info);
2904
  if (htab == NULL)
2905
    return FALSE;
2906
 
2907
  dynobj = htab->elf.dynobj;
2908
 
2909
  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
2910
 
2911
  if (htab->elf.dynamic_sections_created)
2912
    {
2913
      asection *splt;
2914
      Elf32_External_Dyn *dyncon, *dynconend;
2915
 
2916
      splt = bfd_get_section_by_name (dynobj, ".plt");
2917
      BFD_ASSERT (splt != NULL && sdyn != NULL);
2918
 
2919
      dyncon = (Elf32_External_Dyn *) sdyn->contents;
2920
      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
2921
      for (; dyncon < dynconend; dyncon++)
2922
        {
2923
          Elf_Internal_Dyn dyn;
2924
          const char *name;
2925
          bfd_boolean size;
2926
 
2927
          bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
2928
 
2929
          switch (dyn.d_tag)
2930
            {
2931
            case DT_PLTGOT:   name = ".got.plt"; size = FALSE; break;
2932
            case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
2933
            case DT_JMPREL:   name = ".rela.plt"; size = FALSE; break;
2934
            case DT_RELA:     name = ".rela.dyn"; size = FALSE; break;
2935
            case DT_RELASZ:   name = ".rela.dyn"; size = TRUE; break;
2936
            default:      name = NULL; size = FALSE; break;
2937
            }
2938
 
2939
          if (name != NULL)
2940
            {
2941
              asection *s;
2942
 
2943
              s = bfd_get_section_by_name (output_bfd, name);
2944
              if (s == NULL)
2945
                dyn.d_un.d_val = 0;
2946
              else
2947
                {
2948
                  if (! size)
2949
                    dyn.d_un.d_ptr = s->vma;
2950
                  else
2951
                    dyn.d_un.d_val = s->size;
2952
                }
2953
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
2954
            }
2955
        }
2956
 
2957
      /* Clear the first entry in the procedure linkage table,
2958
         and put a nop in the last four bytes.  */
2959
      if (splt->size > 0)
2960
        {
2961
          memset (splt->contents, 0, PLT_ENTRY_SIZE);
2962
          bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop.  */,
2963
                      splt->contents + splt->size - 4);
2964
        }
2965
 
2966
      elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
2967
    }
2968
 
2969
  /* Set the first entry in the global offset table to the address of
2970
     the dynamic section.  */
2971
  sgot = bfd_get_section_by_name (dynobj, ".got.plt");
2972
  if (sgot && sgot->size > 0)
2973
    {
2974
      if (sdyn == NULL)
2975
        bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
2976
      else
2977
        bfd_put_32 (output_bfd,
2978
                    sdyn->output_section->vma + sdyn->output_offset,
2979
                    sgot->contents);
2980
      elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
2981
    }
2982
 
2983
  if (htab->sgot && htab->sgot->size > 0)
2984
    elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
2985
 
2986
  return TRUE;
2987
}
2988
 
2989
/* Hook called by the linker routine which adds symbols from an object
2990
   file.  We use it to put .comm items in .sbss, and not .bss.  */
2991
 
2992
static bfd_boolean
2993
microblaze_elf_add_symbol_hook (bfd *abfd,
2994
                                struct bfd_link_info *info,
2995
                                Elf_Internal_Sym *sym,
2996
                                const char **namep ATTRIBUTE_UNUSED,
2997
                                flagword *flagsp ATTRIBUTE_UNUSED,
2998
                                asection **secp,
2999
                                bfd_vma *valp)
3000
{
3001
  if (sym->st_shndx == SHN_COMMON
3002
      && !info->relocatable
3003
      && sym->st_size <= elf_gp_size (abfd))
3004
    {
3005
      /* Common symbols less than or equal to -G nn bytes are automatically
3006
         put into .sbss.  */
3007
      *secp = bfd_make_section_anyway (abfd, ".sbss");
3008
      if (*secp == NULL
3009
          || ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON))
3010
        return FALSE;
3011
 
3012
      *valp = sym->st_size;
3013
    }
3014
 
3015
  return TRUE;
3016
}
3017
 
3018
 
3019
#define TARGET_BIG_SYM          bfd_elf32_microblaze_vec
3020
#define TARGET_BIG_NAME         "elf32-microblaze"
3021
 
3022
#define ELF_ARCH                bfd_arch_microblaze
3023
#define ELF_TARGET_ID           MICROBLAZE_ELF_DATA
3024
#define ELF_MACHINE_CODE        EM_MICROBLAZE
3025
#define ELF_MACHINE_ALT1        EM_MICROBLAZE_OLD
3026
#define ELF_MAXPAGESIZE         0x4             /* 4k, if we ever have 'em.  */
3027
#define elf_info_to_howto       microblaze_elf_info_to_howto
3028
#define elf_info_to_howto_rel   NULL
3029
 
3030
#define bfd_elf32_bfd_reloc_type_lookup         microblaze_elf_reloc_type_lookup
3031
#define bfd_elf32_bfd_is_local_label_name       microblaze_elf_is_local_label_name
3032
#define elf_backend_relocate_section            microblaze_elf_relocate_section
3033
#define bfd_elf32_bfd_relax_section             microblaze_elf_relax_section
3034
#define bfd_elf32_bfd_reloc_name_lookup         microblaze_elf_reloc_name_lookup
3035
 
3036
#define elf_backend_gc_mark_hook                microblaze_elf_gc_mark_hook
3037
#define elf_backend_gc_sweep_hook               microblaze_elf_gc_sweep_hook
3038
#define elf_backend_check_relocs                microblaze_elf_check_relocs
3039
#define elf_backend_copy_indirect_symbol        microblaze_elf_copy_indirect_symbol
3040
#define bfd_elf32_bfd_link_hash_table_create    microblaze_elf_link_hash_table_create
3041
#define elf_backend_can_gc_sections             1
3042
#define elf_backend_can_refcount                1
3043
#define elf_backend_want_got_plt                1
3044
#define elf_backend_plt_readonly                1
3045
#define elf_backend_got_header_size             12
3046
#define elf_backend_rela_normal                 1
3047
 
3048
#define elf_backend_adjust_dynamic_symbol       microblaze_elf_adjust_dynamic_symbol
3049
#define elf_backend_create_dynamic_sections     microblaze_elf_create_dynamic_sections
3050
#define elf_backend_finish_dynamic_sections     microblaze_elf_finish_dynamic_sections
3051
#define elf_backend_finish_dynamic_symbol       microblaze_elf_finish_dynamic_symbol
3052
#define elf_backend_size_dynamic_sections       microblaze_elf_size_dynamic_sections
3053
#define elf_backend_add_symbol_hook             microblaze_elf_add_symbol_hook
3054
 
3055
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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