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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [elf32-fr30.c] - Blame information for rev 840

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

Line No. Rev Author Line
1 38 julius
/* FR30-specific support for 32-bit ELF.
2
   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
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
        {
582
          /* For relocs against symbols from removed linkonce sections,
583
             or sections discarded by a linker script, we just want the
584
             section contents zeroed.  Avoid any special processing.  */
585
          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
586
          rel->r_info = 0;
587
          rel->r_addend = 0;
588
          continue;
589
        }
590
 
591
      if (info->relocatable)
592
        continue;
593
 
594
      r = fr30_final_link_relocate (howto, input_bfd, input_section,
595
                                     contents, rel, relocation);
596
 
597
      if (r != bfd_reloc_ok)
598
        {
599
          const char * msg = (const char *) NULL;
600
 
601
          switch (r)
602
            {
603
            case bfd_reloc_overflow:
604
              r = info->callbacks->reloc_overflow
605
                (info, (h ? &h->root : NULL), name, howto->name,
606
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
607
              break;
608
 
609
            case bfd_reloc_undefined:
610
              r = info->callbacks->undefined_symbol
611
                (info, name, input_bfd, input_section, rel->r_offset,
612
                 TRUE);
613
              break;
614
 
615
            case bfd_reloc_outofrange:
616
              msg = _("internal error: out of range error");
617
              break;
618
 
619
            case bfd_reloc_notsupported:
620
              msg = _("internal error: unsupported relocation error");
621
              break;
622
 
623
            case bfd_reloc_dangerous:
624
              msg = _("internal error: dangerous relocation");
625
              break;
626
 
627
            default:
628
              msg = _("internal error: unknown error");
629
              break;
630
            }
631
 
632
          if (msg)
633
            r = info->callbacks->warning
634
              (info, msg, name, input_bfd, input_section, rel->r_offset);
635
 
636
          if (! r)
637
            return FALSE;
638
        }
639
    }
640
 
641
  return TRUE;
642
}
643
 
644
/* Return the section that should be marked against GC for a given
645
   relocation.  */
646
 
647
static asection *
648
fr30_elf_gc_mark_hook (asection *sec,
649
                       struct bfd_link_info *info,
650
                       Elf_Internal_Rela *rel,
651
                       struct elf_link_hash_entry *h,
652
                       Elf_Internal_Sym *sym)
653
{
654
  if (h != NULL)
655
    switch (ELF32_R_TYPE (rel->r_info))
656
      {
657
      case R_FR30_GNU_VTINHERIT:
658
      case R_FR30_GNU_VTENTRY:
659
        return NULL;
660
      }
661
 
662
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
663
}
664
 
665
/* Look through the relocs for a section during the first phase.
666
   Since we don't do .gots or .plts, we just need to consider the
667
   virtual table relocs for gc.  */
668
 
669
static bfd_boolean
670
fr30_elf_check_relocs (abfd, info, sec, relocs)
671
     bfd *abfd;
672
     struct bfd_link_info *info;
673
     asection *sec;
674
     const Elf_Internal_Rela *relocs;
675
{
676
  Elf_Internal_Shdr *symtab_hdr;
677
  struct elf_link_hash_entry **sym_hashes;
678
  const Elf_Internal_Rela *rel;
679
  const Elf_Internal_Rela *rel_end;
680
 
681
  if (info->relocatable)
682
    return TRUE;
683
 
684
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
685
  sym_hashes = elf_sym_hashes (abfd);
686
 
687
  rel_end = relocs + sec->reloc_count;
688
  for (rel = relocs; rel < rel_end; rel++)
689
    {
690
      struct elf_link_hash_entry *h;
691
      unsigned long r_symndx;
692
 
693
      r_symndx = ELF32_R_SYM (rel->r_info);
694
      if (r_symndx < symtab_hdr->sh_info)
695
        h = NULL;
696
      else
697
        {
698
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
699
          while (h->root.type == bfd_link_hash_indirect
700
                 || h->root.type == bfd_link_hash_warning)
701
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
702
        }
703
 
704
      switch (ELF32_R_TYPE (rel->r_info))
705
        {
706
        /* This relocation describes the C++ object vtable hierarchy.
707
           Reconstruct it for later use during GC.  */
708
        case R_FR30_GNU_VTINHERIT:
709
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
710
            return FALSE;
711
          break;
712
 
713
        /* This relocation describes which C++ vtable entries are actually
714
           used.  Record for later use during GC.  */
715
        case R_FR30_GNU_VTENTRY:
716
          BFD_ASSERT (h != NULL);
717
          if (h != NULL
718
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
719
            return FALSE;
720
          break;
721
        }
722
    }
723
 
724
  return TRUE;
725
}
726
 
727
#define ELF_ARCH                bfd_arch_fr30
728
#define ELF_MACHINE_CODE        EM_FR30
729
#define ELF_MACHINE_ALT1        EM_CYGNUS_FR30
730
#define ELF_MAXPAGESIZE         0x1000
731
 
732
#define TARGET_BIG_SYM          bfd_elf32_fr30_vec
733
#define TARGET_BIG_NAME         "elf32-fr30"
734
 
735
#define elf_info_to_howto_rel                   NULL
736
#define elf_info_to_howto                       fr30_info_to_howto_rela
737
#define elf_backend_relocate_section            fr30_elf_relocate_section
738
#define elf_backend_gc_mark_hook                fr30_elf_gc_mark_hook
739
#define elf_backend_check_relocs                fr30_elf_check_relocs
740
 
741
#define elf_backend_can_gc_sections             1
742
#define elf_backend_rela_normal                 1
743
 
744
#define bfd_elf32_bfd_reloc_type_lookup         fr30_reloc_type_lookup
745
#define bfd_elf32_bfd_reloc_name_lookup fr30_reloc_name_lookup
746
 
747
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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