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 299

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 166 khays
  if (!(htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got")))
1884
    htab->srelgot = bfd_make_section (dynobj, ".rela.got");
1885 14 khays
  if (htab->srelgot == NULL
1886
      || ! bfd_set_section_flags (dynobj, htab->srelgot, SEC_ALLOC
1887
                                  | SEC_LOAD
1888
                                  | SEC_HAS_CONTENTS
1889
                                  | SEC_IN_MEMORY
1890
                                  | SEC_LINKER_CREATED
1891
                                  | SEC_READONLY)
1892
      || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
1893
    return FALSE;
1894
  return TRUE;
1895
}
1896
 
1897
/* Look through the relocs for a section during the first phase.  */
1898
 
1899
static bfd_boolean
1900
microblaze_elf_check_relocs (bfd * abfd,
1901
                             struct bfd_link_info * info,
1902
                             asection * sec,
1903
                             const Elf_Internal_Rela * relocs)
1904
{
1905
  Elf_Internal_Shdr *           symtab_hdr;
1906
  struct elf_link_hash_entry ** sym_hashes;
1907
  struct elf_link_hash_entry ** sym_hashes_end;
1908
  const Elf_Internal_Rela *     rel;
1909
  const Elf_Internal_Rela *     rel_end;
1910
  struct elf32_mb_link_hash_table *htab;
1911
  asection *sreloc = NULL;
1912
 
1913
  if (info->relocatable)
1914
    return TRUE;
1915
 
1916
  htab = elf32_mb_hash_table (info);
1917
  if (htab == NULL)
1918
    return FALSE;
1919
 
1920
  symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1921
  sym_hashes = elf_sym_hashes (abfd);
1922
  sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
1923
  if (!elf_bad_symtab (abfd))
1924
    sym_hashes_end -= symtab_hdr->sh_info;
1925
 
1926
  rel_end = relocs + sec->reloc_count;
1927
 
1928
  for (rel = relocs; rel < rel_end; rel++)
1929
    {
1930
      unsigned int r_type;
1931
      struct elf_link_hash_entry * h;
1932
      unsigned long r_symndx;
1933
 
1934
      r_symndx = ELF32_R_SYM (rel->r_info);
1935
      r_type = ELF32_R_TYPE (rel->r_info);
1936
 
1937
      if (r_symndx < symtab_hdr->sh_info)
1938
        h = NULL;
1939
      else
1940
        h = sym_hashes [r_symndx - symtab_hdr->sh_info];
1941
 
1942
      switch (r_type)
1943
        {
1944
          /* This relocation describes the C++ object vtable hierarchy.
1945
             Reconstruct it for later use during GC.  */
1946
        case R_MICROBLAZE_GNU_VTINHERIT:
1947
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
1948
            return FALSE;
1949
          break;
1950
 
1951
          /* This relocation describes which C++ vtable entries are actually
1952
             used.  Record for later use during GC.  */
1953
        case R_MICROBLAZE_GNU_VTENTRY:
1954
          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
1955
            return FALSE;
1956
          break;
1957
 
1958
          /* This relocation requires .plt entry.  */
1959
        case R_MICROBLAZE_PLT_64:
1960
          if (h != NULL)
1961
            {
1962
              h->needs_plt = 1;
1963
              h->plt.refcount += 1;
1964
            }
1965
          break;
1966
 
1967
          /* This relocation requires .got entry.  */
1968
        case R_MICROBLAZE_GOT_64:
1969
          if (htab->sgot == NULL)
1970
            {
1971
              if (htab->elf.dynobj == NULL)
1972
                htab->elf.dynobj = abfd;
1973
              if (!create_got_section (htab->elf.dynobj, info))
1974
                return FALSE;
1975
            }
1976
          if (h != NULL)
1977
            {
1978
              h->got.refcount += 1;
1979
            }
1980
          else
1981
            {
1982
              bfd_signed_vma *local_got_refcounts;
1983
 
1984
              /* This is a global offset table entry for a local symbol.  */
1985
              local_got_refcounts = elf_local_got_refcounts (abfd);
1986
              if (local_got_refcounts == NULL)
1987
                {
1988
                  bfd_size_type size;
1989
 
1990
                  size = symtab_hdr->sh_info;
1991
                  size *= sizeof (bfd_signed_vma);
1992
                  local_got_refcounts = bfd_zalloc (abfd, size);
1993
                  if (local_got_refcounts == NULL)
1994
                    return FALSE;
1995
                  elf_local_got_refcounts (abfd) = local_got_refcounts;
1996
                }
1997
              local_got_refcounts[r_symndx] += 1;
1998
            }
1999
          break;
2000
 
2001
        case R_MICROBLAZE_64:
2002
        case R_MICROBLAZE_64_PCREL:
2003
        case R_MICROBLAZE_32:
2004
          {
2005
            if (h != NULL && !info->shared)
2006
              {
2007
                /* we may need a copy reloc.  */
2008
                h->non_got_ref = 1;
2009
 
2010
                /* we may also need a .plt entry.  */
2011
                h->plt.refcount += 1;
2012
                if (ELF32_R_TYPE (rel->r_info) != R_MICROBLAZE_64_PCREL)
2013
                  h->pointer_equality_needed = 1;
2014
              }
2015
 
2016
 
2017
            /* If we are creating a shared library, and this is a reloc
2018
               against a global symbol, or a non PC relative reloc
2019
               against a local symbol, then we need to copy the reloc
2020
               into the shared library.  However, if we are linking with
2021
               -Bsymbolic, we do not need to copy a reloc against a
2022
               global symbol which is defined in an object we are
2023
               including in the link (i.e., DEF_REGULAR is set).  At
2024
               this point we have not seen all the input files, so it is
2025
               possible that DEF_REGULAR is not set now but will be set
2026
               later (it is never cleared).  In case of a weak definition,
2027
               DEF_REGULAR may be cleared later by a strong definition in
2028
               a shared library.  We account for that possibility below by
2029
               storing information in the relocs_copied field of the hash
2030
               table entry.  A similar situation occurs when creating
2031
               shared libraries and symbol visibility changes render the
2032
               symbol local.
2033
 
2034
               If on the other hand, we are creating an executable, we
2035
               may need to keep relocations for symbols satisfied by a
2036
               dynamic library if we manage to avoid copy relocs for the
2037
               symbol.  */
2038
 
2039
            if ((info->shared
2040
                 && (sec->flags & SEC_ALLOC) != 0
2041
                 && (r_type != R_MICROBLAZE_64_PCREL
2042
                     || (h != NULL
2043
                         && (! info->symbolic
2044
                             || h->root.type == bfd_link_hash_defweak
2045
                             || !h->def_regular))))
2046
                || (!info->shared
2047
                    && (sec->flags & SEC_ALLOC) != 0
2048
                    && h != NULL
2049
                    && (h->root.type == bfd_link_hash_defweak
2050
                        || !h->def_regular)))
2051
              {
2052
                struct elf32_mb_dyn_relocs *p;
2053
                struct elf32_mb_dyn_relocs **head;
2054
 
2055
                /* When creating a shared object, we must copy these
2056
                   relocs into the output file.  We create a reloc
2057
                   section in dynobj and make room for the reloc.  */
2058
 
2059
                if (sreloc == NULL)
2060
                  {
2061
                    const char *name;
2062
                    bfd *dynobj;
2063
                    unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
2064
                    unsigned int shnam = _bfd_elf_single_rel_hdr (sec)->sh_name;
2065
 
2066
                    name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
2067
                    if (name == NULL)
2068
                      return FALSE;
2069
 
2070
                    if (strncmp (name, ".rela", 5) != 0
2071
                        || strcmp (bfd_get_section_name (abfd, sec),
2072
                                   name + 5) != 0)
2073
                      {
2074
                        (*_bfd_error_handler)
2075
                          (_("%B: bad relocation section name `%s\'"),
2076
                           abfd, name);
2077
                      }
2078
 
2079
                    if (htab->elf.dynobj == NULL)
2080
                      htab->elf.dynobj = abfd;
2081
                    dynobj = htab->elf.dynobj;
2082
 
2083
                    sreloc = bfd_get_section_by_name (dynobj, name);
2084
                    if (sreloc == NULL)
2085
                      {
2086
                        flagword flags;
2087
 
2088
                        sreloc = bfd_make_section (dynobj, name);
2089
                        flags = (SEC_HAS_CONTENTS | SEC_READONLY
2090
                                 | SEC_IN_MEMORY | SEC_LINKER_CREATED);
2091
                        if ((sec->flags & SEC_ALLOC) != 0)
2092
                          flags |= SEC_ALLOC | SEC_LOAD;
2093
                        if (sreloc == NULL
2094
                            || ! bfd_set_section_flags (dynobj, sreloc, flags)
2095
                            || ! bfd_set_section_alignment (dynobj, sreloc, 2))
2096
                          return FALSE;
2097
                      }
2098
                    elf_section_data (sec)->sreloc = sreloc;
2099
                  }
2100
 
2101
                /* If this is a global symbol, we count the number of
2102
                   relocations we need for this symbol.  */
2103
                if (h != NULL)
2104
                  head = &((struct elf32_mb_link_hash_entry *) h)->dyn_relocs;
2105
                else
2106
                  {
2107
                    /* Track dynamic relocs needed for local syms too.
2108
                       We really need local syms available to do this
2109
                       easily.  Oh well.  */
2110
 
2111
                    asection *s;
2112
                    Elf_Internal_Sym *isym;
2113
                    void *vpp;
2114
 
2115
                    isym = bfd_sym_from_r_symndx (&htab->sym_sec,
2116
                                                  abfd, r_symndx);
2117
                    if (isym == NULL)
2118
                      return FALSE;
2119
 
2120
                    s = bfd_section_from_elf_index (abfd, isym->st_shndx);
2121
                    if (s == NULL)
2122
                      return FALSE;
2123
 
2124
                    vpp = &elf_section_data (s)->local_dynrel;
2125
                    head = (struct elf32_mb_dyn_relocs **) vpp;
2126
                  }
2127
 
2128
                p = *head;
2129
                if (p == NULL || p->sec != sec)
2130
                  {
2131
                    bfd_size_type amt = sizeof *p;
2132
                    p = ((struct elf32_mb_dyn_relocs *)
2133
                         bfd_alloc (htab->elf.dynobj, amt));
2134
                    if (p == NULL)
2135
                      return FALSE;
2136
                    p->next = *head;
2137
                    *head = p;
2138
                    p->sec = sec;
2139
                    p->count = 0;
2140
                    p->pc_count = 0;
2141
                  }
2142
 
2143
                p->count += 1;
2144
                if (r_type == R_MICROBLAZE_64_PCREL)
2145
                  p->pc_count += 1;
2146
              }
2147
          }
2148
          break;
2149
        }
2150
    }
2151
 
2152
  return TRUE;
2153
}
2154
 
2155
static bfd_boolean
2156
microblaze_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
2157
{
2158
  struct elf32_mb_link_hash_table *htab;
2159
 
2160
  htab = elf32_mb_hash_table (info);
2161
  if (htab == NULL)
2162
    return FALSE;
2163
 
2164
  if (!htab->sgot && !create_got_section (dynobj, info))
2165
    return FALSE;
2166
 
2167
  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
2168
    return FALSE;
2169
 
2170
  htab->splt = bfd_get_section_by_name (dynobj, ".plt");
2171
  htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
2172
  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
2173
  if (!info->shared)
2174
    htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
2175
 
2176
  if (!htab->splt || !htab->srelplt || !htab->sdynbss
2177
      || (!info->shared && !htab->srelbss))
2178
    abort ();
2179
 
2180
  return TRUE;
2181
}
2182
 
2183
/* Copy the extra info we tack onto an elf_link_hash_entry.  */
2184
 
2185
static void
2186
microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
2187
                                     struct elf_link_hash_entry *dir,
2188
                                     struct elf_link_hash_entry *ind)
2189
{
2190
  struct elf32_mb_link_hash_entry *edir, *eind;
2191
 
2192
  edir = (struct elf32_mb_link_hash_entry *) dir;
2193
  eind = (struct elf32_mb_link_hash_entry *) ind;
2194
 
2195
  if (eind->dyn_relocs != NULL)
2196
    {
2197
      if (edir->dyn_relocs != NULL)
2198
        {
2199
          struct elf32_mb_dyn_relocs **pp;
2200
          struct elf32_mb_dyn_relocs *p;
2201
 
2202
          if (ind->root.type == bfd_link_hash_indirect)
2203
            abort ();
2204
 
2205
          /* Add reloc counts against the weak sym to the strong sym
2206
             list.  Merge any entries against the same section.  */
2207
          for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
2208
            {
2209
              struct elf32_mb_dyn_relocs *q;
2210
 
2211
              for (q = edir->dyn_relocs; q != NULL; q = q->next)
2212
                if (q->sec == p->sec)
2213
                  {
2214
                    q->pc_count += p->pc_count;
2215
                    q->count += p->count;
2216
                    *pp = p->next;
2217
                    break;
2218
                  }
2219
              if (q == NULL)
2220
                pp = &p->next;
2221
            }
2222
          *pp = edir->dyn_relocs;
2223
        }
2224
 
2225
      edir->dyn_relocs = eind->dyn_relocs;
2226
      eind->dyn_relocs = NULL;
2227
    }
2228
 
2229
  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
2230
}
2231
 
2232
static bfd_boolean
2233
microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
2234
                                      struct elf_link_hash_entry *h)
2235
{
2236
  struct elf32_mb_link_hash_table *htab;
2237
  struct elf32_mb_link_hash_entry * eh;
2238
  struct elf32_mb_dyn_relocs *p;
2239
  asection *sdynbss, *s;
2240
  unsigned int power_of_two;
2241
  bfd *dynobj;
2242
 
2243
  htab = elf32_mb_hash_table (info);
2244
  if (htab == NULL)
2245
    return FALSE;
2246
 
2247
  /* If this is a function, put it in the procedure linkage table.  We
2248
     will fill in the contents of the procedure linkage table later,
2249
     when we know the address of the .got section.  */
2250
  if (h->type == STT_FUNC
2251
      || h->needs_plt)
2252
    {
2253
      if (h->plt.refcount <= 0
2254
          || SYMBOL_CALLS_LOCAL (info, h)
2255
          || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
2256
              && h->root.type == bfd_link_hash_undefweak))
2257
        {
2258
          /* This case can occur if we saw a PLT reloc in an input
2259
             file, but the symbol was never referred to by a dynamic
2260
             object, or if all references were garbage collected.  In
2261
             such a case, we don't actually need to build a procedure
2262
             linkage table, and we can just do a PC32 reloc instead.  */
2263
          h->plt.offset = (bfd_vma) -1;
2264
          h->needs_plt = 0;
2265
        }
2266
 
2267
      return TRUE;
2268
    }
2269
  else
2270
    /* It's possible that we incorrectly decided a .plt reloc was
2271
       needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
2272
       check_relocs.  We can't decide accurately between function and
2273
       non-function syms in check-relocs;  Objects loaded later in
2274
       the link may change h->type.  So fix it now.  */
2275
    h->plt.offset = (bfd_vma) -1;
2276
 
2277
  /* If this is a weak symbol, and there is a real definition, the
2278
     processor independent code will have arranged for us to see the
2279
     real definition first, and we can just use the same value.  */
2280
  if (h->u.weakdef != NULL)
2281
    {
2282
      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
2283
                  || h->u.weakdef->root.type == bfd_link_hash_defweak);
2284
      h->root.u.def.section = h->u.weakdef->root.u.def.section;
2285
      h->root.u.def.value = h->u.weakdef->root.u.def.value;
2286
      return TRUE;
2287
    }
2288
 
2289
  /* This is a reference to a symbol defined by a dynamic object which
2290
     is not a function.  */
2291
 
2292
  /* If we are creating a shared library, we must presume that the
2293
     only references to the symbol are via the global offset table.
2294
     For such cases we need not do anything here; the relocations will
2295
     be handled correctly by relocate_section.  */
2296
  if (info->shared)
2297
    return TRUE;
2298
 
2299
  /* If there are no references to this symbol that do not use the
2300
     GOT, we don't need to generate a copy reloc.  */
2301
  if (!h->non_got_ref)
2302
    return TRUE;
2303
 
2304
  /* If -z nocopyreloc was given, we won't generate them either.  */
2305
  if (info->nocopyreloc)
2306
    {
2307
      h->non_got_ref = 0;
2308
      return TRUE;
2309
    }
2310
 
2311
  eh = (struct elf32_mb_link_hash_entry *) h;
2312
  for (p = eh->dyn_relocs; p != NULL; p = p->next)
2313
    {
2314
      s = p->sec->output_section;
2315
      if (s != NULL && (s->flags & SEC_READONLY) != 0)
2316
        break;
2317
    }
2318
 
2319
  /* If we didn't find any dynamic relocs in read-only sections, then
2320
     we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
2321
  if (p == NULL)
2322
    {
2323
      h->non_got_ref = 0;
2324
      return TRUE;
2325
    }
2326
 
2327
  /* We must allocate the symbol in our .dynbss section, which will
2328
     become part of the .bss section of the executable.  There will be
2329
     an entry for this symbol in the .dynsym section.  The dynamic
2330
     object will contain position independent code, so all references
2331
     from the dynamic object to this symbol will go through the global
2332
     offset table.  The dynamic linker will use the .dynsym entry to
2333
     determine the address it must put in the global offset table, so
2334
     both the dynamic object and the regular object will refer to the
2335
     same memory location for the variable.  */
2336
 
2337
  /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
2338
     to copy the initial value out of the dynamic object and into the
2339
     runtime process image.  */
2340
  dynobj = elf_hash_table (info)->dynobj;
2341
  BFD_ASSERT (dynobj != NULL);
2342
  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
2343
    {
2344
      htab->srelbss->size += sizeof (Elf32_External_Rela);
2345
      h->needs_copy = 1;
2346
    }
2347
 
2348
  /* We need to figure out the alignment required for this symbol.  I
2349
     have no idea how ELF linkers handle this.  */
2350
  power_of_two = bfd_log2 (h->size);
2351
  if (power_of_two > 3)
2352
    power_of_two = 3;
2353
 
2354
  sdynbss = htab->sdynbss;
2355
  /* Apply the required alignment.  */
2356
  sdynbss->size = BFD_ALIGN (sdynbss->size, (bfd_size_type) (1 << power_of_two));
2357
  if (power_of_two > bfd_get_section_alignment (dynobj, sdynbss))
2358
    {
2359
      if (! bfd_set_section_alignment (dynobj, sdynbss, power_of_two))
2360
        return FALSE;
2361
    }
2362
 
2363
  /* Define the symbol as being at this point in the section.  */
2364
  h->root.u.def.section = sdynbss;
2365
  h->root.u.def.value = sdynbss->size;
2366
 
2367
  /* Increment the section size to make room for the symbol.  */
2368
  sdynbss->size += h->size;
2369
  return TRUE;
2370
}
2371
 
2372
/* Allocate space in .plt, .got and associated reloc sections for
2373
   dynamic relocs.  */
2374
 
2375
static bfd_boolean
2376
allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
2377
{
2378
  struct bfd_link_info *info;
2379
  struct elf32_mb_link_hash_table *htab;
2380
  struct elf32_mb_link_hash_entry *eh;
2381
  struct elf32_mb_dyn_relocs *p;
2382
 
2383
  if (h->root.type == bfd_link_hash_indirect)
2384
    return TRUE;
2385
 
2386
  info = (struct bfd_link_info *) dat;
2387
  htab = elf32_mb_hash_table (info);
2388
  if (htab == NULL)
2389
    return FALSE;
2390
 
2391
  if (htab->elf.dynamic_sections_created
2392
      && h->plt.refcount > 0)
2393
    {
2394
      /* Make sure this symbol is output as a dynamic symbol.
2395
         Undefined weak syms won't yet be marked as dynamic.  */
2396
      if (h->dynindx == -1
2397
          && !h->forced_local)
2398
        {
2399
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
2400
            return FALSE;
2401
        }
2402
 
2403
      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
2404
        {
2405
          asection *s = htab->splt;
2406
 
2407
          /* The first entry in .plt is reserved.  */
2408
          if (s->size == 0)
2409
            s->size = PLT_ENTRY_SIZE;
2410
 
2411
          h->plt.offset = s->size;
2412
 
2413
          /* If this symbol is not defined in a regular file, and we are
2414
             not generating a shared library, then set the symbol to this
2415
             location in the .plt.  This is required to make function
2416
             pointers compare as equal between the normal executable and
2417
             the shared library.  */
2418
          if (! info->shared
2419
              && !h->def_regular)
2420
            {
2421
              h->root.u.def.section = s;
2422
              h->root.u.def.value = h->plt.offset;
2423
            }
2424
 
2425
          /* Make room for this entry.  */
2426
          s->size += PLT_ENTRY_SIZE;
2427
 
2428
          /* We also need to make an entry in the .got.plt section, which
2429
             will be placed in the .got section by the linker script.  */
2430
          htab->sgotplt->size += 4;
2431
 
2432
          /* We also need to make an entry in the .rel.plt section.  */
2433
          htab->srelplt->size += sizeof (Elf32_External_Rela);
2434
        }
2435
      else
2436
        {
2437
          h->plt.offset = (bfd_vma) -1;
2438
          h->needs_plt = 0;
2439
        }
2440
    }
2441
  else
2442
    {
2443
      h->plt.offset = (bfd_vma) -1;
2444
      h->needs_plt = 0;
2445
    }
2446
 
2447
  if (h->got.refcount > 0)
2448
    {
2449
      asection *s;
2450
 
2451
      /* Make sure this symbol is output as a dynamic symbol.
2452
         Undefined weak syms won't yet be marked as dynamic.  */
2453
      if (h->dynindx == -1
2454
          && !h->forced_local)
2455
        {
2456
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
2457
            return FALSE;
2458
        }
2459
 
2460
      s = htab->sgot;
2461
      h->got.offset = s->size;
2462
      s->size += 4;
2463
      htab->srelgot->size += sizeof (Elf32_External_Rela);
2464
    }
2465
  else
2466
    h->got.offset = (bfd_vma) -1;
2467
 
2468
  eh = (struct elf32_mb_link_hash_entry *) h;
2469
  if (eh->dyn_relocs == NULL)
2470
    return TRUE;
2471
 
2472
  /* In the shared -Bsymbolic case, discard space allocated for
2473
     dynamic pc-relative relocs against symbols which turn out to be
2474
     defined in regular objects.  For the normal shared case, discard
2475
     space for pc-relative relocs that have become local due to symbol
2476
     visibility changes.  */
2477
 
2478
  if (info->shared)
2479
    {
2480
      if (h->def_regular
2481
          && (h->forced_local
2482
              || info->symbolic))
2483
        {
2484
          struct elf32_mb_dyn_relocs **pp;
2485
 
2486
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
2487
            {
2488
              p->count -= p->pc_count;
2489
              p->pc_count = 0;
2490
              if (p->count == 0)
2491
                *pp = p->next;
2492
              else
2493
                pp = &p->next;
2494
            }
2495
        }
2496
    }
2497
  else
2498
    {
2499
      /* For the non-shared case, discard space for relocs against
2500
         symbols which turn out to need copy relocs or are not
2501
         dynamic.  */
2502
 
2503
      if (!h->non_got_ref
2504
          && ((h->def_dynamic
2505
               && !h->def_regular)
2506
              || (htab->elf.dynamic_sections_created
2507
                  && (h->root.type == bfd_link_hash_undefweak
2508
                      || h->root.type == bfd_link_hash_undefined))))
2509
        {
2510
          /* Make sure this symbol is output as a dynamic symbol.
2511
             Undefined weak syms won't yet be marked as dynamic.  */
2512
          if (h->dynindx == -1
2513
              && !h->forced_local)
2514
            {
2515
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
2516
                return FALSE;
2517
            }
2518
 
2519
          /* If that succeeded, we know we'll be keeping all the
2520
             relocs.  */
2521
          if (h->dynindx != -1)
2522
            goto keep;
2523
        }
2524
 
2525
      eh->dyn_relocs = NULL;
2526
 
2527
    keep: ;
2528
    }
2529
 
2530
  /* Finally, allocate space.  */
2531
  for (p = eh->dyn_relocs; p != NULL; p = p->next)
2532
    {
2533
      asection *sreloc = elf_section_data (p->sec)->sreloc;
2534
      sreloc->size += p->count * sizeof (Elf32_External_Rela);
2535
    }
2536
 
2537
  return TRUE;
2538
}
2539
 
2540
/* Set the sizes of the dynamic sections.  */
2541
 
2542
static bfd_boolean
2543
microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
2544
                                      struct bfd_link_info *info)
2545
{
2546
  struct elf32_mb_link_hash_table *htab;
2547
  bfd *dynobj;
2548
  asection *s;
2549
  bfd *ibfd;
2550
 
2551
  htab = elf32_mb_hash_table (info);
2552
  if (htab == NULL)
2553
    return FALSE;
2554
 
2555
  dynobj = htab->elf.dynobj;
2556
  BFD_ASSERT (dynobj != NULL);
2557
 
2558
  /* Set up .got offsets for local syms, and space for local dynamic
2559
     relocs.  */
2560
  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
2561
    {
2562
      bfd_signed_vma *local_got;
2563
      bfd_signed_vma *end_local_got;
2564
      bfd_size_type locsymcount;
2565
      Elf_Internal_Shdr *symtab_hdr;
2566
      asection *srel;
2567
 
2568
      if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
2569
        continue;
2570
 
2571
      for (s = ibfd->sections; s != NULL; s = s->next)
2572
        {
2573
          struct elf32_mb_dyn_relocs *p;
2574
 
2575
          for (p = ((struct elf32_mb_dyn_relocs *)
2576
                    elf_section_data (s)->local_dynrel);
2577
               p != NULL;
2578
               p = p->next)
2579
            {
2580
              if (!bfd_is_abs_section (p->sec)
2581
                  && bfd_is_abs_section (p->sec->output_section))
2582
                {
2583
                  /* Input section has been discarded, either because
2584
                     it is a copy of a linkonce section or due to
2585
                     linker script /DISCARD/, so we'll be discarding
2586
                     the relocs too.  */
2587
                }
2588
              else if (p->count != 0)
2589
                {
2590
                  srel = elf_section_data (p->sec)->sreloc;
2591
                  srel->size += p->count * sizeof (Elf32_External_Rela);
2592
                  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
2593
                    info->flags |= DF_TEXTREL;
2594
                }
2595
            }
2596
        }
2597
 
2598
      local_got = elf_local_got_refcounts (ibfd);
2599
      if (!local_got)
2600
        continue;
2601
 
2602
      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
2603
      locsymcount = symtab_hdr->sh_info;
2604
      end_local_got = local_got + locsymcount;
2605
      s = htab->sgot;
2606
      srel = htab->srelgot;
2607
 
2608
      for (; local_got < end_local_got; ++local_got)
2609
        {
2610
          if (*local_got > 0)
2611
            {
2612
              *local_got = s->size;
2613
              s->size += 4;
2614
              if (info->shared)
2615
                srel->size += sizeof (Elf32_External_Rela);
2616
            }
2617
          else
2618
            *local_got = (bfd_vma) -1;
2619
        }
2620
    }
2621
 
2622
  /* Allocate global sym .plt and .got entries, and space for global
2623
     sym dynamic relocs.  */
2624
  elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
2625
 
2626
  if (elf_hash_table (info)->dynamic_sections_created)
2627
    {
2628
      /* Make space for the trailing nop in .plt.  */
2629
      if (htab->splt->size > 0)
2630
        htab->splt->size += 4;
2631
    }
2632
 
2633
  /* The check_relocs and adjust_dynamic_symbol entry points have
2634
     determined the sizes of the various dynamic sections.  Allocate
2635
     memory for them.  */
2636
  for (s = dynobj->sections; s != NULL; s = s->next)
2637
    {
2638
      const char *name;
2639
      bfd_boolean strip = FALSE;
2640
 
2641
      if ((s->flags & SEC_LINKER_CREATED) == 0)
2642
        continue;
2643
 
2644
      /* It's OK to base decisions on the section name, because none
2645
         of the dynobj section names depend upon the input files.  */
2646
      name = bfd_get_section_name (dynobj, s);
2647
 
2648
      if (strncmp (name, ".rela", 5) == 0)
2649
        {
2650
          if (s->size == 0)
2651
            {
2652
              /* If we don't need this section, strip it from the
2653
                 output file.  This is to handle .rela.bss and
2654
                 .rela.plt.  We must create it in
2655
                 create_dynamic_sections, because it must be created
2656
                 before the linker maps input sections to output
2657
                 sections.  The linker does that before
2658
                 adjust_dynamic_symbol is called, and it is that
2659
                 function which decides whether anything needs to go
2660
                 into these sections.  */
2661
              strip = TRUE;
2662
            }
2663
          else
2664
            {
2665
              /* We use the reloc_count field as a counter if we need
2666
                 to copy relocs into the output file.  */
2667
              s->reloc_count = 0;
2668
            }
2669
        }
2670
      else if (s != htab->splt && s != htab->sgot && s != htab->sgotplt)
2671
        {
2672
          /* It's not one of our sections, so don't allocate space.  */
2673
          continue;
2674
        }
2675
 
2676
      if (strip)
2677
        {
2678
          s->flags |= SEC_EXCLUDE;
2679
          continue;
2680
        }
2681
 
2682
      /* Allocate memory for the section contents.  */
2683
      /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
2684
         Unused entries should be reclaimed before the section's contents
2685
         are written out, but at the moment this does not happen.  Thus in
2686
         order to prevent writing out garbage, we initialise the section's
2687
         contents to zero.  */
2688
      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
2689
      if (s->contents == NULL && s->size != 0)
2690
        return FALSE;
2691
    }
2692
 
2693
  if (elf_hash_table (info)->dynamic_sections_created)
2694
    {
2695
      /* Add some entries to the .dynamic section.  We fill in the
2696
         values later, in microblaze_elf_finish_dynamic_sections, but we
2697
         must add the entries now so that we get the correct size for
2698
         the .dynamic section.  The DT_DEBUG entry is filled in by the
2699
         dynamic linker and used by the debugger.  */
2700
#define add_dynamic_entry(TAG, VAL)                     \
2701
      _bfd_elf_add_dynamic_entry (info, TAG, VAL)
2702
 
2703
      if (info->executable)
2704
        {
2705
          if (!add_dynamic_entry (DT_DEBUG, 0))
2706
            return FALSE;
2707
        }
2708
 
2709
      if (!add_dynamic_entry (DT_RELA, 0)
2710
          || !add_dynamic_entry (DT_RELASZ, 0)
2711
          || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
2712
        return FALSE;
2713
 
2714
      if (htab->splt->size != 0)
2715
        {
2716
          if (!add_dynamic_entry (DT_PLTGOT, 0)
2717
              || !add_dynamic_entry (DT_PLTRELSZ, 0)
2718
              || !add_dynamic_entry (DT_PLTREL, DT_RELA)
2719
              || !add_dynamic_entry (DT_JMPREL, 0)
2720
              || !add_dynamic_entry (DT_BIND_NOW, 1))
2721
            return FALSE;
2722
        }
2723
 
2724
      if (info->flags & DF_TEXTREL)
2725
        {
2726
          if (!add_dynamic_entry (DT_TEXTREL, 0))
2727
            return FALSE;
2728
        }
2729
    }
2730
#undef add_dynamic_entry
2731
  return TRUE;
2732
}
2733
 
2734
/* Finish up dynamic symbol handling.  We set the contents of various
2735
   dynamic sections here.  */
2736
 
2737
static bfd_boolean
2738
microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
2739
                                      struct bfd_link_info *info,
2740
                                      struct elf_link_hash_entry *h,
2741
                                      Elf_Internal_Sym *sym)
2742
{
2743
  struct elf32_mb_link_hash_table *htab;
2744
 
2745
  htab = elf32_mb_hash_table (info);
2746
  if (htab == NULL)
2747
    return FALSE;
2748
 
2749
  if (h->plt.offset != (bfd_vma) -1)
2750
    {
2751
      asection *splt;
2752
      asection *srela;
2753
      asection *sgotplt;
2754
      Elf_Internal_Rela rela;
2755
      bfd_byte *loc;
2756
      bfd_vma plt_index;
2757
      bfd_vma got_offset;
2758
      bfd_vma got_addr;
2759
 
2760
      /* This symbol has an entry in the procedure linkage table.  Set
2761
         it up.  */
2762
      BFD_ASSERT (h->dynindx != -1);
2763
 
2764
      splt = htab->splt;
2765
      srela = htab->srelplt;
2766
      sgotplt = htab->sgotplt;
2767
      BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
2768
 
2769
      plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved.  */
2770
      got_offset = (plt_index + 3) * 4; /* 3 reserved ???  */
2771
      got_addr = got_offset;
2772
 
2773
      /* For non-PIC objects we need absolute address of the GOT entry.  */
2774
      if (!info->shared)
2775
        got_addr += htab->sgotplt->output_section->vma + sgotplt->output_offset;
2776
 
2777
      /* Fill in the entry in the procedure linkage table.  */
2778
      bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
2779
                  splt->contents + h->plt.offset);
2780
      if (info->shared)
2781
        bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
2782
                    splt->contents + h->plt.offset + 4);
2783
      else
2784
        bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
2785
                    splt->contents + h->plt.offset + 4);
2786
      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
2787
                  splt->contents + h->plt.offset + 8);
2788
      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
2789
                  splt->contents + h->plt.offset + 12);
2790
 
2791
      /* Any additions to the .got section??? */
2792
      /*      bfd_put_32 (output_bfd,
2793
              splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
2794
              sgotplt->contents + got_offset); */
2795
 
2796
      /* Fill in the entry in the .rela.plt section.  */
2797
      rela.r_offset = (sgotplt->output_section->vma
2798
                       + sgotplt->output_offset
2799
                       + got_offset);
2800
      rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
2801
      rela.r_addend = 0;
2802
      loc = srela->contents;
2803
      loc += plt_index * sizeof (Elf32_External_Rela);
2804
      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
2805
 
2806
      if (!h->def_regular)
2807
        {
2808
          /* Mark the symbol as undefined, rather than as defined in
2809
             the .plt section.  Zero the value.  */
2810
          sym->st_shndx = SHN_UNDEF;
2811
          sym->st_value = 0;
2812
        }
2813
    }
2814
 
2815
  if (h->got.offset != (bfd_vma) -1)
2816
    {
2817
      asection *sgot;
2818
      asection *srela;
2819
      Elf_Internal_Rela rela;
2820
      bfd_byte *loc;
2821
 
2822
      /* This symbol has an entry in the global offset table.  Set it
2823
         up.  */
2824
 
2825
      sgot = htab->sgot;
2826
      srela = htab->srelgot;
2827
      BFD_ASSERT (sgot != NULL && srela != NULL);
2828
 
2829
      rela.r_offset = (sgot->output_section->vma
2830
                       + sgot->output_offset
2831
                       + (h->got.offset &~ (bfd_vma) 1));
2832
 
2833
      /* If this is a -Bsymbolic link, and the symbol is defined
2834
         locally, we just want to emit a RELATIVE reloc.  Likewise if
2835
         the symbol was forced to be local because of a version file.
2836
         The entry in the global offset table will already have been
2837
         initialized in the relocate_section function.  */
2838
      if (info->shared
2839
          && (info->symbolic || h->dynindx == -1)
2840
          && h->def_regular)
2841
        {
2842
          asection *sec = h->root.u.def.section;
2843
          rela.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
2844
          rela.r_addend = (h->root.u.def.value
2845
                           + sec->output_section->vma
2846
                           + sec->output_offset);
2847
        }
2848
      else
2849
        {
2850
          rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_GLOB_DAT);
2851
          rela.r_addend = 0;
2852
        }
2853
 
2854
      bfd_put_32 (output_bfd, (bfd_vma) 0,
2855
                  sgot->contents + (h->got.offset &~ (bfd_vma) 1));
2856
      loc = srela->contents;
2857
      loc += srela->reloc_count++ * sizeof (Elf32_External_Rela);
2858
      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
2859
    }
2860
 
2861
  if (h->needs_copy)
2862
    {
2863
      asection *s;
2864
      Elf_Internal_Rela rela;
2865
      bfd_byte *loc;
2866
 
2867
      /* This symbols needs a copy reloc.  Set it up.  */
2868
 
2869
      BFD_ASSERT (h->dynindx != -1);
2870
 
2871
      s = bfd_get_section_by_name (h->root.u.def.section->owner,
2872
                                   ".rela.bss");
2873
      BFD_ASSERT (s != NULL);
2874
 
2875
      rela.r_offset = (h->root.u.def.value
2876
                       + h->root.u.def.section->output_section->vma
2877
                       + h->root.u.def.section->output_offset);
2878
      rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
2879
      rela.r_addend = 0;
2880
      loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
2881
      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
2882
    }
2883
 
2884
  /* Mark some specially defined symbols as absolute.  */
2885
  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
2886
      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
2887
      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
2888
    sym->st_shndx = SHN_ABS;
2889
 
2890
  return TRUE;
2891
}
2892
 
2893
 
2894
/* Finish up the dynamic sections.  */
2895
 
2896
static bfd_boolean
2897
microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
2898
                                        struct bfd_link_info *info)
2899
{
2900
  bfd *dynobj;
2901
  asection *sdyn, *sgot;
2902
  struct elf32_mb_link_hash_table *htab;
2903
 
2904
  htab = elf32_mb_hash_table (info);
2905
  if (htab == NULL)
2906
    return FALSE;
2907
 
2908
  dynobj = htab->elf.dynobj;
2909
 
2910
  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
2911
 
2912
  if (htab->elf.dynamic_sections_created)
2913
    {
2914
      asection *splt;
2915
      Elf32_External_Dyn *dyncon, *dynconend;
2916
 
2917
      splt = bfd_get_section_by_name (dynobj, ".plt");
2918
      BFD_ASSERT (splt != NULL && sdyn != NULL);
2919
 
2920
      dyncon = (Elf32_External_Dyn *) sdyn->contents;
2921
      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
2922
      for (; dyncon < dynconend; dyncon++)
2923
        {
2924
          Elf_Internal_Dyn dyn;
2925
          const char *name;
2926
          bfd_boolean size;
2927
 
2928
          bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
2929
 
2930
          switch (dyn.d_tag)
2931
            {
2932
            case DT_PLTGOT:   name = ".got.plt"; size = FALSE; break;
2933
            case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
2934
            case DT_JMPREL:   name = ".rela.plt"; size = FALSE; break;
2935
            case DT_RELA:     name = ".rela.dyn"; size = FALSE; break;
2936
            case DT_RELASZ:   name = ".rela.dyn"; size = TRUE; break;
2937
            default:      name = NULL; size = FALSE; break;
2938
            }
2939
 
2940
          if (name != NULL)
2941
            {
2942
              asection *s;
2943
 
2944
              s = bfd_get_section_by_name (output_bfd, name);
2945
              if (s == NULL)
2946
                dyn.d_un.d_val = 0;
2947
              else
2948
                {
2949
                  if (! size)
2950
                    dyn.d_un.d_ptr = s->vma;
2951
                  else
2952
                    dyn.d_un.d_val = s->size;
2953
                }
2954
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
2955
            }
2956
        }
2957
 
2958
      /* Clear the first entry in the procedure linkage table,
2959
         and put a nop in the last four bytes.  */
2960
      if (splt->size > 0)
2961
        {
2962
          memset (splt->contents, 0, PLT_ENTRY_SIZE);
2963
          bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop.  */,
2964
                      splt->contents + splt->size - 4);
2965
        }
2966
 
2967
      elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
2968
    }
2969
 
2970
  /* Set the first entry in the global offset table to the address of
2971
     the dynamic section.  */
2972
  sgot = bfd_get_section_by_name (dynobj, ".got.plt");
2973
  if (sgot && sgot->size > 0)
2974
    {
2975
      if (sdyn == NULL)
2976
        bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
2977
      else
2978
        bfd_put_32 (output_bfd,
2979
                    sdyn->output_section->vma + sdyn->output_offset,
2980
                    sgot->contents);
2981
      elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
2982
    }
2983
 
2984
  if (htab->sgot && htab->sgot->size > 0)
2985
    elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
2986
 
2987
  return TRUE;
2988
}
2989
 
2990
/* Hook called by the linker routine which adds symbols from an object
2991
   file.  We use it to put .comm items in .sbss, and not .bss.  */
2992
 
2993
static bfd_boolean
2994
microblaze_elf_add_symbol_hook (bfd *abfd,
2995
                                struct bfd_link_info *info,
2996
                                Elf_Internal_Sym *sym,
2997
                                const char **namep ATTRIBUTE_UNUSED,
2998
                                flagword *flagsp ATTRIBUTE_UNUSED,
2999
                                asection **secp,
3000
                                bfd_vma *valp)
3001
{
3002
  if (sym->st_shndx == SHN_COMMON
3003
      && !info->relocatable
3004
      && sym->st_size <= elf_gp_size (abfd))
3005
    {
3006
      /* Common symbols less than or equal to -G nn bytes are automatically
3007
         put into .sbss.  */
3008
      *secp = bfd_make_section_anyway (abfd, ".sbss");
3009
      if (*secp == NULL
3010
          || ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON))
3011
        return FALSE;
3012
 
3013
      *valp = sym->st_size;
3014
    }
3015
 
3016
  return TRUE;
3017
}
3018
 
3019
 
3020
#define TARGET_BIG_SYM          bfd_elf32_microblaze_vec
3021
#define TARGET_BIG_NAME         "elf32-microblaze"
3022
 
3023
#define ELF_ARCH                bfd_arch_microblaze
3024
#define ELF_TARGET_ID           MICROBLAZE_ELF_DATA
3025
#define ELF_MACHINE_CODE        EM_MICROBLAZE
3026
#define ELF_MACHINE_ALT1        EM_MICROBLAZE_OLD
3027
#define ELF_MAXPAGESIZE         0x4             /* 4k, if we ever have 'em.  */
3028
#define elf_info_to_howto       microblaze_elf_info_to_howto
3029
#define elf_info_to_howto_rel   NULL
3030
 
3031
#define bfd_elf32_bfd_reloc_type_lookup         microblaze_elf_reloc_type_lookup
3032
#define bfd_elf32_bfd_is_local_label_name       microblaze_elf_is_local_label_name
3033
#define elf_backend_relocate_section            microblaze_elf_relocate_section
3034
#define bfd_elf32_bfd_relax_section             microblaze_elf_relax_section
3035
#define bfd_elf32_bfd_reloc_name_lookup         microblaze_elf_reloc_name_lookup
3036
 
3037
#define elf_backend_gc_mark_hook                microblaze_elf_gc_mark_hook
3038
#define elf_backend_gc_sweep_hook               microblaze_elf_gc_sweep_hook
3039
#define elf_backend_check_relocs                microblaze_elf_check_relocs
3040
#define elf_backend_copy_indirect_symbol        microblaze_elf_copy_indirect_symbol
3041
#define bfd_elf32_bfd_link_hash_table_create    microblaze_elf_link_hash_table_create
3042
#define elf_backend_can_gc_sections             1
3043
#define elf_backend_can_refcount                1
3044
#define elf_backend_want_got_plt                1
3045
#define elf_backend_plt_readonly                1
3046
#define elf_backend_got_header_size             12
3047
#define elf_backend_rela_normal                 1
3048
 
3049
#define elf_backend_adjust_dynamic_symbol       microblaze_elf_adjust_dynamic_symbol
3050
#define elf_backend_create_dynamic_sections     microblaze_elf_create_dynamic_sections
3051
#define elf_backend_finish_dynamic_sections     microblaze_elf_finish_dynamic_sections
3052
#define elf_backend_finish_dynamic_symbol       microblaze_elf_finish_dynamic_symbol
3053
#define elf_backend_size_dynamic_sections       microblaze_elf_size_dynamic_sections
3054
#define elf_backend_add_symbol_hook             microblaze_elf_add_symbol_hook
3055
 
3056
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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