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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 14 khays
/* FR30-specific support for 32-bit ELF.
2
   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
3
   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 Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include "sysdep.h"
23
#include "bfd.h"
24
#include "libbfd.h"
25
#include "elf-bfd.h"
26
#include "elf/fr30.h"
27
 
28
/* Forward declarations.  */
29
static bfd_reloc_status_type fr30_elf_i20_reloc
30
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
31
static bfd_reloc_status_type fr30_elf_i32_reloc
32
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
33
static reloc_howto_type * fr30_reloc_type_lookup
34
  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
35
static void fr30_info_to_howto_rela
36
  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
37
static bfd_boolean fr30_elf_relocate_section
38
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
39
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
40
static bfd_reloc_status_type fr30_final_link_relocate
41
  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
42
           Elf_Internal_Rela *, bfd_vma));
43
static bfd_boolean fr30_elf_check_relocs
44
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
45
           const Elf_Internal_Rela *));
46
 
47
static reloc_howto_type fr30_elf_howto_table [] =
48
{
49
  /* This reloc does nothing.  */
50
  HOWTO (R_FR30_NONE,           /* type */
51
         0,                      /* rightshift */
52
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
53
         32,                    /* bitsize */
54
         FALSE,                 /* pc_relative */
55
         0,                      /* bitpos */
56
         complain_overflow_bitfield, /* complain_on_overflow */
57
         bfd_elf_generic_reloc, /* special_function */
58
         "R_FR30_NONE",         /* name */
59
         FALSE,                 /* partial_inplace */
60
         0,                      /* src_mask */
61
         0,                      /* dst_mask */
62
         FALSE),                /* pcrel_offset */
63
 
64
  /* An 8 bit absolute relocation.  */
65
  HOWTO (R_FR30_8,              /* type */
66
         0,                      /* rightshift */
67
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
68
         8,                     /* bitsize */
69
         FALSE,                 /* pc_relative */
70
         4,                     /* bitpos */
71
         complain_overflow_bitfield, /* complain_on_overflow */
72
         bfd_elf_generic_reloc, /* special_function */
73
         "R_FR30_8",            /* name */
74
         FALSE,                 /* partial_inplace */
75
         0x0000,                /* src_mask */
76
         0x0ff0,                /* dst_mask */
77
         FALSE),                /* pcrel_offset */
78
 
79
  /* A 20 bit absolute relocation.  */
80
  HOWTO (R_FR30_20,             /* type */
81
         0,                      /* rightshift */
82
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
83
         20,                    /* bitsize */
84
         FALSE,                 /* pc_relative */
85
         0,                      /* bitpos */
86
         complain_overflow_bitfield, /* complain_on_overflow */
87
         fr30_elf_i20_reloc,    /* special_function */
88
         "R_FR30_20",           /* name */
89
         FALSE,                 /* partial_inplace */
90
         0x00000000,            /* src_mask */
91
         0x00f0ffff,            /* dst_mask */
92
         FALSE),                /* pcrel_offset */
93
 
94
  /* A 32 bit absolute relocation.  */
95
  HOWTO (R_FR30_32,             /* type */
96
         0,                      /* rightshift */
97
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
98
         32,                    /* bitsize */
99
         FALSE,                 /* pc_relative */
100
         0,                      /* bitpos */
101
         complain_overflow_bitfield, /* complain_on_overflow */
102
         bfd_elf_generic_reloc, /* special_function */
103
         "R_FR30_32",           /* name */
104
         FALSE,                 /* partial_inplace */
105
         0x00000000,            /* src_mask */
106
         0xffffffff,            /* dst_mask */
107
         FALSE),                /* pcrel_offset */
108
 
109
  /* A 32 bit into 48 bits absolute relocation.  */
110
  HOWTO (R_FR30_48,             /* type */
111
         0,                      /* rightshift */
112
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
113
         32,                    /* bitsize */
114
         FALSE,                 /* pc_relative */
115
         0,                      /* bitpos */
116
         complain_overflow_bitfield, /* complain_on_overflow */
117
         fr30_elf_i32_reloc,    /* special_function */
118
         "R_FR30_48",           /* name */
119
         FALSE,                 /* partial_inplace */
120
         0x00000000,            /* src_mask */
121
         0xffffffff,            /* dst_mask */
122
         FALSE),                /* pcrel_offset */
123
 
124
  /* A 6 bit absolute relocation.  */
125
  HOWTO (R_FR30_6_IN_4,         /* type */
126
         2,                     /* rightshift */
127
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
128
         6,                     /* bitsize */
129
         FALSE,                 /* pc_relative */
130
         4,                     /* bitpos */
131
         complain_overflow_unsigned, /* complain_on_overflow */
132
         bfd_elf_generic_reloc, /* special_function */
133
         "R_FR30_6_IN_4",       /* name */
134
         FALSE,                 /* partial_inplace */
135
         0x0000,                /* src_mask */
136
         0x00f0,                /* dst_mask */
137
         FALSE),                /* pcrel_offset */
138
 
139
  /* An 8 bit absolute relocation.  */
140
  HOWTO (R_FR30_8_IN_8,         /* type */
141
         0,                      /* rightshift */
142
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
143
         8,                     /* bitsize */
144
         FALSE,                 /* pc_relative */
145
         4,                     /* bitpos */
146
         complain_overflow_signed, /* complain_on_overflow */
147
         bfd_elf_generic_reloc,/* special_function */
148
         "R_FR30_8_IN_8",       /* name */
149
         FALSE,                 /* partial_inplace */
150
         0x0000,                /* src_mask */
151
         0x0ff0,                /* dst_mask */
152
         FALSE),                /* pcrel_offset */
153
 
154
  /* A 9 bit absolute relocation.  */
155
  HOWTO (R_FR30_9_IN_8,         /* type */
156
         1,                     /* rightshift */
157
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
158
         9,                     /* bitsize */
159
         FALSE,                 /* pc_relative */
160
         4,                     /* bitpos */
161
         complain_overflow_signed, /* complain_on_overflow */
162
         bfd_elf_generic_reloc,/* special_function */
163
         "R_FR30_9_IN_8",       /* name */
164
         FALSE,                 /* partial_inplace */
165
         0x0000,                /* src_mask */
166
         0x0ff0,                /* dst_mask */
167
         FALSE),                /* pcrel_offset */
168
 
169
  /* A 10 bit absolute relocation.  */
170
  HOWTO (R_FR30_10_IN_8,        /* type */
171
         2,                     /* rightshift */
172
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
173
         10,                    /* bitsize */
174
         FALSE,                 /* pc_relative */
175
         4,                     /* bitpos */
176
         complain_overflow_signed, /* complain_on_overflow */
177
         bfd_elf_generic_reloc,/* special_function */
178
         "R_FR30_10_IN_8",      /* name */
179
         FALSE,                 /* partial_inplace */
180
         0x0000,                /* src_mask */
181
         0x0ff0,                /* dst_mask */
182
         FALSE),                /* pcrel_offset */
183
 
184
  /* A PC relative 9 bit relocation, right shifted by 1.  */
185
  HOWTO (R_FR30_9_PCREL,        /* type */
186
         1,                     /* rightshift */
187
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
188
         9,                     /* bitsize */
189
         TRUE,                  /* pc_relative */
190
         0,                      /* bitpos */
191
         complain_overflow_signed, /* complain_on_overflow */
192
         bfd_elf_generic_reloc, /* special_function */
193
         "R_FR30_9_PCREL",      /* name */
194
         FALSE,                 /* partial_inplace */
195
         0x0000,                /* src_mask */
196
         0x00ff,                /* dst_mask */
197
         FALSE),                /* pcrel_offset */
198
 
199
  /* A PC relative 12 bit relocation, right shifted by 1.  */
200
  HOWTO (R_FR30_12_PCREL,       /* type */
201
         1,                     /* rightshift */
202
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
203
         12,                    /* bitsize */
204
         TRUE,                  /* pc_relative */
205
         0,                      /* bitpos */
206
         complain_overflow_signed, /* complain_on_overflow */
207
         bfd_elf_generic_reloc, /* special_function */
208
         "R_FR30_12_PCREL",     /* name */
209
         FALSE,                 /* partial_inplace */
210
         0x0000,                /* src_mask */
211
         0x07ff,                /* dst_mask */
212
         FALSE),                /* pcrel_offset */
213
  /* GNU extension to record C++ vtable hierarchy */
214
  HOWTO (R_FR30_GNU_VTINHERIT, /* type */
215
         0,                     /* rightshift */
216
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
217
         0,                     /* bitsize */
218
         FALSE,                 /* pc_relative */
219
         0,                     /* bitpos */
220
         complain_overflow_dont, /* complain_on_overflow */
221
         NULL,                  /* special_function */
222
         "R_FR30_GNU_VTINHERIT", /* name */
223
         FALSE,                 /* partial_inplace */
224
         0,                     /* src_mask */
225
         0,                     /* dst_mask */
226
         FALSE),                /* pcrel_offset */
227
 
228
  /* GNU extension to record C++ vtable member usage */
229
  HOWTO (R_FR30_GNU_VTENTRY,     /* type */
230
         0,                     /* rightshift */
231
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
232
         0,                     /* bitsize */
233
         FALSE,                 /* pc_relative */
234
         0,                     /* bitpos */
235
         complain_overflow_dont, /* complain_on_overflow */
236
         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
237
         "R_FR30_GNU_VTENTRY",   /* name */
238
         FALSE,                 /* partial_inplace */
239
         0,                     /* src_mask */
240
         0,                     /* dst_mask */
241
         FALSE),                /* pcrel_offset */
242
};
243
 
244
/* Utility to actually perform an R_FR30_20 reloc.  */
245
 
246
static bfd_reloc_status_type
247
fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
248
                    input_section, output_bfd, error_message)
249
     bfd *abfd;
250
     arelent *reloc_entry;
251
     asymbol *symbol;
252
     PTR data;
253
     asection *input_section;
254
     bfd *output_bfd;
255
     char **error_message ATTRIBUTE_UNUSED;
256
{
257
  bfd_vma relocation;
258
  unsigned long x;
259
 
260
  /* This part is from bfd_elf_generic_reloc.  */
261
  if (output_bfd != (bfd *) NULL
262
      && (symbol->flags & BSF_SECTION_SYM) == 0
263
      && (! reloc_entry->howto->partial_inplace
264
          || reloc_entry->addend == 0))
265
    {
266
      reloc_entry->address += input_section->output_offset;
267
      return bfd_reloc_ok;
268
    }
269
 
270
  if (output_bfd != NULL)
271
    /* FIXME: See bfd_perform_relocation.  Is this right?  */
272
    return bfd_reloc_ok;
273
 
274
  relocation =
275
    symbol->value
276
    + symbol->section->output_section->vma
277
    + symbol->section->output_offset
278
    + reloc_entry->addend;
279
 
280
  if (relocation > (((bfd_vma) 1 << 20) - 1))
281
    return bfd_reloc_overflow;
282
 
283
  x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
284
  x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
285
  bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
286
 
287
  return bfd_reloc_ok;
288
}
289
 
290
/* Utility to actually perform a R_FR30_48 reloc.  */
291
 
292
static bfd_reloc_status_type
293
fr30_elf_i32_reloc (abfd, reloc_entry, symbol, data,
294
                    input_section, output_bfd, error_message)
295
     bfd *abfd;
296
     arelent *reloc_entry;
297
     asymbol *symbol;
298
     PTR data;
299
     asection *input_section;
300
     bfd *output_bfd;
301
     char **error_message ATTRIBUTE_UNUSED;
302
{
303
  bfd_vma relocation;
304
 
305
  /* This part is from bfd_elf_generic_reloc.  */
306
  if (output_bfd != (bfd *) NULL
307
      && (symbol->flags & BSF_SECTION_SYM) == 0
308
      && (! reloc_entry->howto->partial_inplace
309
          || reloc_entry->addend == 0))
310
    {
311
      reloc_entry->address += input_section->output_offset;
312
      return bfd_reloc_ok;
313
    }
314
 
315
  if (output_bfd != NULL)
316
    /* FIXME: See bfd_perform_relocation.  Is this right?  */
317
    return bfd_reloc_ok;
318
 
319
  relocation =
320
    symbol->value
321
    + symbol->section->output_section->vma
322
    + symbol->section->output_offset
323
    + reloc_entry->addend;
324
 
325
  bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
326
 
327
  return bfd_reloc_ok;
328
}
329
 
330
/* Map BFD reloc types to FR30 ELF reloc types.  */
331
 
332
struct fr30_reloc_map
333
{
334
  bfd_reloc_code_real_type bfd_reloc_val;
335
  unsigned int fr30_reloc_val;
336
};
337
 
338
static const struct fr30_reloc_map fr30_reloc_map [] =
339
{
340
  { BFD_RELOC_NONE,           R_FR30_NONE },
341
  { BFD_RELOC_8,              R_FR30_8 },
342
  { BFD_RELOC_FR30_20,        R_FR30_20 },
343
  { BFD_RELOC_32,             R_FR30_32 },
344
  { BFD_RELOC_FR30_48,        R_FR30_48 },
345
  { BFD_RELOC_FR30_6_IN_4,    R_FR30_6_IN_4 },
346
  { BFD_RELOC_FR30_8_IN_8,    R_FR30_8_IN_8 },
347
  { BFD_RELOC_FR30_9_IN_8,    R_FR30_9_IN_8 },
348
  { BFD_RELOC_FR30_10_IN_8,   R_FR30_10_IN_8 },
349
  { BFD_RELOC_FR30_9_PCREL,   R_FR30_9_PCREL },
350
  { BFD_RELOC_FR30_12_PCREL,  R_FR30_12_PCREL },
351
  { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
352
  { BFD_RELOC_VTABLE_ENTRY,   R_FR30_GNU_VTENTRY },
353
};
354
 
355
static reloc_howto_type *
356
fr30_reloc_type_lookup (abfd, code)
357
     bfd *abfd ATTRIBUTE_UNUSED;
358
     bfd_reloc_code_real_type code;
359
{
360
  unsigned int i;
361
 
362
  for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
363
       --i;)
364
    if (fr30_reloc_map [i].bfd_reloc_val == code)
365
      return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
366
 
367
  return NULL;
368
}
369
 
370
static reloc_howto_type *
371
fr30_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
372
{
373
  unsigned int i;
374
 
375
  for (i = 0;
376
       i < sizeof (fr30_elf_howto_table) / sizeof (fr30_elf_howto_table[0]);
377
       i++)
378
    if (fr30_elf_howto_table[i].name != NULL
379
        && strcasecmp (fr30_elf_howto_table[i].name, r_name) == 0)
380
      return &fr30_elf_howto_table[i];
381
 
382
  return NULL;
383
}
384
 
385
/* Set the howto pointer for an FR30 ELF reloc.  */
386
 
387
static void
388
fr30_info_to_howto_rela (abfd, cache_ptr, dst)
389
     bfd *abfd ATTRIBUTE_UNUSED;
390
     arelent *cache_ptr;
391
     Elf_Internal_Rela *dst;
392
{
393
  unsigned int r_type;
394
 
395
  r_type = ELF32_R_TYPE (dst->r_info);
396
  BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
397
  cache_ptr->howto = & fr30_elf_howto_table [r_type];
398
}
399
 
400
/* Perform a single relocation.  By default we use the standard BFD
401
   routines, but a few relocs, we have to do them ourselves.  */
402
 
403
static bfd_reloc_status_type
404
fr30_final_link_relocate (howto, input_bfd, input_section, contents, rel,
405
                          relocation)
406
     reloc_howto_type *howto;
407
     bfd *input_bfd;
408
     asection *input_section;
409
     bfd_byte *contents;
410
     Elf_Internal_Rela *rel;
411
     bfd_vma relocation;
412
{
413
  bfd_reloc_status_type r = bfd_reloc_ok;
414
  bfd_vma x;
415
  bfd_signed_vma srel;
416
 
417
  switch (howto->type)
418
    {
419
    case R_FR30_20:
420
      contents   += rel->r_offset;
421
      relocation += rel->r_addend;
422
 
423
      if (relocation > ((1 << 20) - 1))
424
        return bfd_reloc_overflow;
425
 
426
      x = bfd_get_32 (input_bfd, contents);
427
      x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
428
      bfd_put_32 (input_bfd, x, contents);
429
      break;
430
 
431
    case R_FR30_48:
432
      contents   += rel->r_offset + 2;
433
      relocation += rel->r_addend;
434
      bfd_put_32 (input_bfd, relocation, contents);
435
      break;
436
 
437
    case R_FR30_9_PCREL:
438
      contents   += rel->r_offset + 1;
439
      srel = (bfd_signed_vma) relocation;
440
      srel += rel->r_addend;
441
      srel -= rel->r_offset;
442
      srel -= 2;  /* Branch instructions add 2 to the PC...  */
443
      srel -= (input_section->output_section->vma +
444
                     input_section->output_offset);
445
 
446
      if (srel & 1)
447
        return bfd_reloc_outofrange;
448
      if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
449
        return bfd_reloc_overflow;
450
 
451
      bfd_put_8 (input_bfd, srel >> 1, contents);
452
      break;
453
 
454
    case R_FR30_12_PCREL:
455
      contents   += rel->r_offset;
456
      srel = (bfd_signed_vma) relocation;
457
      srel += rel->r_addend;
458
      srel -= rel->r_offset;
459
      srel -= 2; /* Branch instructions add 2 to the PC...  */
460
      srel -= (input_section->output_section->vma +
461
                     input_section->output_offset);
462
 
463
      if (srel & 1)
464
        return bfd_reloc_outofrange;
465
      if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
466
          return bfd_reloc_overflow;
467
 
468
      x = bfd_get_16 (input_bfd, contents);
469
      x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
470
      bfd_put_16 (input_bfd, x, contents);
471
      break;
472
 
473
    default:
474
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
475
                                    contents, rel->r_offset,
476
                                    relocation, rel->r_addend);
477
    }
478
 
479
  return r;
480
}
481
 
482
/* Relocate an FR30 ELF section.
483
 
484
   The RELOCATE_SECTION function is called by the new ELF backend linker
485
   to handle the relocations for a section.
486
 
487
   The relocs are always passed as Rela structures; if the section
488
   actually uses Rel structures, the r_addend field will always be
489
   zero.
490
 
491
   This function is responsible for adjusting the section contents as
492
   necessary, and (if using Rela relocs and generating a relocatable
493
   output file) adjusting the reloc addend as necessary.
494
 
495
   This function does not have to worry about setting the reloc
496
   address or the reloc symbol index.
497
 
498
   LOCAL_SYMS is a pointer to the swapped in local symbols.
499
 
500
   LOCAL_SECTIONS is an array giving the section in the input file
501
   corresponding to the st_shndx field of each local symbol.
502
 
503
   The global hash table entry for the global symbols can be found
504
   via elf_sym_hashes (input_bfd).
505
 
506
   When generating relocatable output, this function must handle
507
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
508
   going to be the section symbol corresponding to the output
509
   section, which means that the addend must be adjusted
510
   accordingly.  */
511
 
512
static bfd_boolean
513
fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
514
                           contents, relocs, local_syms, local_sections)
515
     bfd *output_bfd;
516
     struct bfd_link_info *info;
517
     bfd *input_bfd;
518
     asection *input_section;
519
     bfd_byte *contents;
520
     Elf_Internal_Rela *relocs;
521
     Elf_Internal_Sym *local_syms;
522
     asection **local_sections;
523
{
524
  Elf_Internal_Shdr *symtab_hdr;
525
  struct elf_link_hash_entry **sym_hashes;
526
  Elf_Internal_Rela *rel;
527
  Elf_Internal_Rela *relend;
528
 
529
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
530
  sym_hashes = elf_sym_hashes (input_bfd);
531
  relend     = relocs + input_section->reloc_count;
532
 
533
  for (rel = relocs; rel < relend; rel ++)
534
    {
535
      reloc_howto_type *howto;
536
      unsigned long r_symndx;
537
      Elf_Internal_Sym *sym;
538
      asection *sec;
539
      struct elf_link_hash_entry *h;
540
      bfd_vma relocation;
541
      bfd_reloc_status_type r;
542
      const char *name;
543
      int r_type;
544
 
545
      r_type = ELF32_R_TYPE (rel->r_info);
546
 
547
      if (   r_type == R_FR30_GNU_VTINHERIT
548
          || r_type == R_FR30_GNU_VTENTRY)
549
        continue;
550
 
551
      r_symndx = ELF32_R_SYM (rel->r_info);
552
 
553
      howto  = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
554
      h      = NULL;
555
      sym    = NULL;
556
      sec    = NULL;
557
 
558
      if (r_symndx < symtab_hdr->sh_info)
559
        {
560
          sym = local_syms + r_symndx;
561
          sec = local_sections [r_symndx];
562
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
563
 
564
          name = bfd_elf_string_from_elf_section
565
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
566
          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
567
        }
568
      else
569
        {
570
          bfd_boolean unresolved_reloc, warned;
571
 
572
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
573
                                   r_symndx, symtab_hdr, sym_hashes,
574
                                   h, sec, relocation,
575
                                   unresolved_reloc, warned);
576
 
577
          name = h->root.root.string;
578
        }
579
 
580
      if (sec != NULL && elf_discarded_section (sec))
581
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
582
                                         rel, relend, howto, contents);
583
 
584
      if (info->relocatable)
585
        continue;
586
 
587
      r = fr30_final_link_relocate (howto, input_bfd, input_section,
588
                                     contents, rel, relocation);
589
 
590
      if (r != bfd_reloc_ok)
591
        {
592
          const char * msg = (const char *) NULL;
593
 
594
          switch (r)
595
            {
596
            case bfd_reloc_overflow:
597
              r = info->callbacks->reloc_overflow
598
                (info, (h ? &h->root : NULL), name, howto->name,
599
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
600
              break;
601
 
602
            case bfd_reloc_undefined:
603
              r = info->callbacks->undefined_symbol
604
                (info, name, input_bfd, input_section, rel->r_offset,
605
                 TRUE);
606
              break;
607
 
608
            case bfd_reloc_outofrange:
609
              msg = _("internal error: out of range error");
610
              break;
611
 
612
            case bfd_reloc_notsupported:
613
              msg = _("internal error: unsupported relocation error");
614
              break;
615
 
616
            case bfd_reloc_dangerous:
617
              msg = _("internal error: dangerous relocation");
618
              break;
619
 
620
            default:
621
              msg = _("internal error: unknown error");
622
              break;
623
            }
624
 
625
          if (msg)
626
            r = info->callbacks->warning
627
              (info, msg, name, input_bfd, input_section, rel->r_offset);
628
 
629
          if (! r)
630
            return FALSE;
631
        }
632
    }
633
 
634
  return TRUE;
635
}
636
 
637
/* Return the section that should be marked against GC for a given
638
   relocation.  */
639
 
640
static asection *
641
fr30_elf_gc_mark_hook (asection *sec,
642
                       struct bfd_link_info *info,
643
                       Elf_Internal_Rela *rel,
644
                       struct elf_link_hash_entry *h,
645
                       Elf_Internal_Sym *sym)
646
{
647
  if (h != NULL)
648
    switch (ELF32_R_TYPE (rel->r_info))
649
      {
650
      case R_FR30_GNU_VTINHERIT:
651
      case R_FR30_GNU_VTENTRY:
652
        return NULL;
653
      }
654
 
655
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
656
}
657
 
658
/* Look through the relocs for a section during the first phase.
659
   Since we don't do .gots or .plts, we just need to consider the
660
   virtual table relocs for gc.  */
661
 
662
static bfd_boolean
663
fr30_elf_check_relocs (abfd, info, sec, relocs)
664
     bfd *abfd;
665
     struct bfd_link_info *info;
666
     asection *sec;
667
     const Elf_Internal_Rela *relocs;
668
{
669
  Elf_Internal_Shdr *symtab_hdr;
670
  struct elf_link_hash_entry **sym_hashes;
671
  const Elf_Internal_Rela *rel;
672
  const Elf_Internal_Rela *rel_end;
673
 
674
  if (info->relocatable)
675
    return TRUE;
676
 
677
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
678
  sym_hashes = elf_sym_hashes (abfd);
679
 
680
  rel_end = relocs + sec->reloc_count;
681
  for (rel = relocs; rel < rel_end; rel++)
682
    {
683
      struct elf_link_hash_entry *h;
684
      unsigned long r_symndx;
685
 
686
      r_symndx = ELF32_R_SYM (rel->r_info);
687
      if (r_symndx < symtab_hdr->sh_info)
688
        h = NULL;
689
      else
690
        {
691
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
692
          while (h->root.type == bfd_link_hash_indirect
693
                 || h->root.type == bfd_link_hash_warning)
694
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
695
        }
696
 
697
      switch (ELF32_R_TYPE (rel->r_info))
698
        {
699
        /* This relocation describes the C++ object vtable hierarchy.
700
           Reconstruct it for later use during GC.  */
701
        case R_FR30_GNU_VTINHERIT:
702
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
703
            return FALSE;
704
          break;
705
 
706
        /* This relocation describes which C++ vtable entries are actually
707
           used.  Record for later use during GC.  */
708
        case R_FR30_GNU_VTENTRY:
709
          BFD_ASSERT (h != NULL);
710
          if (h != NULL
711
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
712
            return FALSE;
713
          break;
714
        }
715
    }
716
 
717
  return TRUE;
718
}
719
 
720
#define ELF_ARCH                bfd_arch_fr30
721
#define ELF_MACHINE_CODE        EM_FR30
722
#define ELF_MACHINE_ALT1        EM_CYGNUS_FR30
723
#define ELF_MAXPAGESIZE         0x1000
724
 
725
#define TARGET_BIG_SYM          bfd_elf32_fr30_vec
726
#define TARGET_BIG_NAME         "elf32-fr30"
727
 
728
#define elf_info_to_howto_rel                   NULL
729
#define elf_info_to_howto                       fr30_info_to_howto_rela
730
#define elf_backend_relocate_section            fr30_elf_relocate_section
731
#define elf_backend_gc_mark_hook                fr30_elf_gc_mark_hook
732
#define elf_backend_check_relocs                fr30_elf_check_relocs
733
 
734
#define elf_backend_can_gc_sections             1
735
#define elf_backend_rela_normal                 1
736
 
737
#define bfd_elf32_bfd_reloc_type_lookup         fr30_reloc_type_lookup
738
#define bfd_elf32_bfd_reloc_name_lookup fr30_reloc_name_lookup
739
 
740
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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