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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [bfd/] [elf32-microblaze.c] - Blame information for rev 819

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

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

powered by: WebSVN 2.1.0

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